Class: StoryTeller::IO::Session

Inherits:
Object
  • Object
show all
Extended by:
SessionManagementMethods
Includes:
SessionStateManagementMethods
Defined in:
lib/story_teller/session.rb

Overview

rubocop: disable Metrics/ClassLength

Constant Summary collapse

Promiscuous =

These states accept any input, including no input

Set.new
ExitCommandPattern =
/^(exit|quit|q)$/i.freeze

Constants included from SessionManagementMethods

SessionManagementMethods::SessionsByChannel, SessionManagementMethods::SessionsByPlayer

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SessionManagementMethods

[], []=, add_promiscuous_states, channels, get, include?, of, players, register, register_player, release_player, sessions_by_channel, sessions_by_player, unregister

Methods included from SessionStateManagementMethods

#[], #[]=, #delete, #include?, #keys, #values

Constructor Details

#initialize(channel = nil, machine: nil, player: nil, state: :playing, settings: {}) ⇒ Session

rubocop: disable Metrics/MethodLength



163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/story_teller/session.rb', line 163

def initialize(channel = nil, machine: nil, player: nil, state: :playing, settings: {})
  @channel = channel
  @machine = machine
  @player = nil
  @state = state
  @last_good_state = state
  @session_data = {}
  @settings = settings
  @status = nil
  @last_activity = Time.now

  self.class.register(channel, self) unless channel.nil?
  control(player) unless player.nil?
end

Instance Attribute Details

#channelObject

Returns the value of attribute channel.



156
157
158
# File 'lib/story_teller/session.rb', line 156

def channel
  @channel
end

#inboundObject (readonly)

Returns the value of attribute inbound.



157
158
159
# File 'lib/story_teller/session.rb', line 157

def inbound
  @inbound
end

#last_activityObject (readonly)

Returns the value of attribute last_activity.



157
158
159
# File 'lib/story_teller/session.rb', line 157

def last_activity
  @last_activity
end

#last_good_stateObject (readonly)

Returns the value of attribute last_good_state.



157
158
159
# File 'lib/story_teller/session.rb', line 157

def last_good_state
  @last_good_state
end

#machineObject

Returns the value of attribute machine.



156
157
158
# File 'lib/story_teller/session.rb', line 156

def machine
  @machine
end

#outboundObject (readonly)

Returns the value of attribute outbound.



157
158
159
# File 'lib/story_teller/session.rb', line 157

def outbound
  @outbound
end

#playerObject

Returns the value of attribute player.



156
157
158
# File 'lib/story_teller/session.rb', line 156

def player
  @player
end

#previousObject (readonly)

Returns the value of attribute previous.



157
158
159
# File 'lib/story_teller/session.rb', line 157

def previous
  @previous
end

#settingsObject (readonly) Also known as: preferences

Returns the value of attribute settings.



157
158
159
# File 'lib/story_teller/session.rb', line 157

def settings
  @settings
end

#stateObject

Returns the value of attribute state.



156
157
158
# File 'lib/story_teller/session.rb', line 156

def state
  @state
end

#statusObject

Returns the value of attribute status.



156
157
158
# File 'lib/story_teller/session.rb', line 156

def status
  @status
end

Instance Method Details

#after_updateObject



209
210
211
# File 'lib/story_teller/session.rb', line 209

def after_update
  # Override for application implementations
end

#confusedObject



266
267
268
269
270
271
272
# File 'lib/story_teller/session.rb', line 266

def confused
  println "The session is in an unknown state: #{@state}"
  println "The last known good session state was: #{@last_good_state}"
  println "Reverting the session to its last known good state, for better or worse."
  prompt
  @last_good_state
end

#control(player) ⇒ Object



189
190
191
192
193
194
# File 'lib/story_teller/session.rb', line 189

def control(player)
  self.class.release_player(@player, self)
  @player = player
  self.class.register_player(player, self) unless player.nil?
  self
end

#exit_command?(message) ⇒ Boolean

Returns:

  • (Boolean)


228
229
230
# File 'lib/story_teller/session.rb', line 228

def exit_command?(message)
  !Promiscuous.include?(@state) && ExitCommandPattern.match?(message)
end

#expose_to(machine) ⇒ Object



221
222
223
224
# File 'lib/story_teller/session.rb', line 221

def expose_to(machine)
  machine.instance_variable_set(:@buffer, @buffer)
  machine.instance_variable_set(:@session, self)
end

#init_channel_session(channel) ⇒ Object



181
182
183
184
185
186
187
# File 'lib/story_teller/session.rb', line 181

def init_channel_session(channel)
  Session[channel] = self
  @channel = channel
  @inbound = Inbound.new(self)
  @outbound = Outbound.new(self)
  @last_activity = Time.now
end

#process(message, machine = @machine) ⇒ Object

Raises:

  • (ArgumentError)


232
233
234
235
236
237
238
239
240
241
242
# File 'lib/story_teller/session.rb', line 232

def process(message, machine = @machine)
  raise ArgumentError, 'session machine is required' if machine.nil?

  @machine = machine
  @buffer = sanitize(message)
  @last_activity = Time.now
  @status = :active

  expose_to(machine)
  update(machine)
end

#receive(message) ⇒ Object



196
197
198
199
200
201
# File 'lib/story_teller/session.rb', line 196

def receive(message)
  return if message.nil? # It is okay if the message parameter is an empty string
  return disconnected if @channel.nil?
  return disconnected unless @channel.isActive() && @channel.isOpen()
  process(sanitize(message))
end

#respondObject



244
245
246
# File 'lib/story_teller/session.rb', line 244

def respond
  flush_io
end

#safely_progress(machine = self) ⇒ Object



248
249
250
251
252
253
254
255
# File 'lib/story_teller/session.rb', line 248

def safely_progress(machine = self)
  @state = machine.public_send(@state)
  raise 'Bad state machine implementation: nil state' if @state.nil?
rescue StandardError => e
  log.error "Error updating state: #{e.message}", e
  log.warn "Reverting to last known good state #{@last_good_state}"
  @state = @last_good_state
end

#sanitize(message) ⇒ Object



213
214
215
# File 'lib/story_teller/session.rb', line 213

def sanitize(message)
  message.to_s.strip.scan(/[[:print:]]/).join
end

#sessionObject



217
218
219
# File 'lib/story_teller/session.rb', line 217

def session
  self
end

#update(machine = @machine) ⇒ Object



203
204
205
206
207
# File 'lib/story_teller/session.rb', line 203

def update(machine = @machine)
  safely_progress(machine)
  after_update if self.respond_to?(:after_update)
  @last_good_state = @state unless @state == :confused
end

#valid_state?(machine = self) ⇒ Boolean

Returns:

  • (Boolean)


257
258
259
260
261
262
263
264
# File 'lib/story_teller/session.rb', line 257

def valid_state?(machine = self)
  case @state
  when String, Symbol
    machine.respond_to?(@state)
  else
    false
  end
end