Class: Inform::IO::Session

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

Overview

TODO: Refactor method implementations into modules

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SessionManagementMethods

[], []=, add_promiscuous_states, get, include?, register, sessions_by_channel, unregister

Methods included from SessionStateManagementMethods

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

Constructor Details

#initialize(channel = nil) ⇒ Session

Returns a new instance of Session.



102
103
104
105
106
107
108
# File 'lib/story_teller/session.rb', line 102

def initialize(channel = nil)
  init_channel_session(channel) unless channel.nil?
  @status = nil
  @last_good_state = @state = default if respond_to? :default
  @session_data = {}
  @settings = {}
end

Instance Attribute Details

#channelObject

Returns the value of attribute channel.



99
100
101
# File 'lib/story_teller/session.rb', line 99

def channel
  @channel
end

#inboundObject (readonly)

Returns the value of attribute inbound.



100
101
102
# File 'lib/story_teller/session.rb', line 100

def inbound
  @inbound
end

#last_activityObject (readonly)

Returns the value of attribute last_activity.



100
101
102
# File 'lib/story_teller/session.rb', line 100

def last_activity
  @last_activity
end

#last_good_stateObject (readonly)

Returns the value of attribute last_good_state.



100
101
102
# File 'lib/story_teller/session.rb', line 100

def last_good_state
  @last_good_state
end

#outboundObject (readonly)

Returns the value of attribute outbound.



100
101
102
# File 'lib/story_teller/session.rb', line 100

def outbound
  @outbound
end

#previousObject (readonly)

Returns the value of attribute previous.



100
101
102
# File 'lib/story_teller/session.rb', line 100

def previous
  @previous
end

#settingsObject (readonly)

Returns the value of attribute settings.



100
101
102
# File 'lib/story_teller/session.rb', line 100

def settings
  @settings
end

#stateObject

Returns the value of attribute state.



99
100
101
# File 'lib/story_teller/session.rb', line 99

def state
  @state
end

#statusObject

Returns the value of attribute status.



99
100
101
# File 'lib/story_teller/session.rb', line 99

def status
  @status
end

Instance Method Details

#after_updateObject



131
132
133
# File 'lib/story_teller/session.rb', line 131

def after_update
  # Override for application implementations
end

#confusedObject



185
186
187
188
189
190
191
# File 'lib/story_teller/session.rb', line 185

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

#exit_command?(message) ⇒ Boolean

Returns:

  • (Boolean)


145
146
147
# File 'lib/story_teller/session.rb', line 145

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

#init_channel_session(channel) ⇒ Object



110
111
112
113
114
115
116
# File 'lib/story_teller/session.rb', line 110

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) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/story_teller/session.rb', line 149

def process(message)
  return disconnect if exit_command?(message)
  @buffer = message
  @last_activity = Time.now
  @status = :active
  if valid_state?
    update
  else
    @inbound.publish @buffer
  end

  respond
end

#receive(message) ⇒ Object



118
119
120
121
122
123
# File 'lib/story_teller/session.rb', line 118

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



163
164
165
# File 'lib/story_teller/session.rb', line 163

def respond
  flush_io
end

#safely_progress(machine = self) ⇒ Object



167
168
169
170
171
172
173
174
# File 'lib/story_teller/session.rb', line 167

def safely_progress(machine = self)
  @state = machine.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



135
136
137
# File 'lib/story_teller/session.rb', line 135

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

#sessionObject



139
140
141
# File 'lib/story_teller/session.rb', line 139

def session
  self
end

#update(machine = self) ⇒ Object



125
126
127
128
129
# File 'lib/story_teller/session.rb', line 125

def update(machine = self)
  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)


176
177
178
179
180
181
182
183
# File 'lib/story_teller/session.rb', line 176

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