sms_beholder.rb 3.53 KB
Newer Older
Joe Libipl's avatar
Joe Libipl committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
require 'json'
require 'sinatra/base'

# Sinatra-derived class for easy testing
class SMSBeholder < Sinatra::Base
  configure do
    # Don't log them. We'll do that ourself
    set :dump_errors, false

    # Don't capture any errors. Throw them up the stack
    set :raise_errors, true

    # Disable internal middleware for presenting errors
    # as useful HTML pages
    set :show_exceptions, false
  end

  # The set of game states. After being loaded from a JSON file, should never change.
  module GameStates
    @states = {}

    def self.load
      @states = JSON.parse(File.open('script.json', 'r').read)
    end

    def self.states
      @states
    end

    def self.story(state)
      if @states[state] && @states[state].key?('story')
        String.new(@states[state]['story'])
      else
        ''
      end
    end

    def self.selections(state)
      response = ''
      if @states[state] && @states[state].key?('selection')
        @states[state]['selection'].keys.each_with_index do |selection, index|
          response += "\n#{index + 1}) #{selection}"
        end
      end
Joe Libipl's avatar
Joe Libipl committed
45
46
47
48
49
      if @states[state] && @states[state].key?('conditionalSelection')
        @states[state]['conditionalSelection']['constants'].keys.each_with_index do |selection, index|
          response += "\n#{index + 1}) #{selection}"
        end
      end
Joe Libipl's avatar
Joe Libipl committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
      response
    end
  end

  player_data = {}
  GameStates.load

  def process_input(params, player)
    puts "Processing input for player #{player} params #{params}"

    body = params['Body'] || 'NoBody'

    ## State is the state that was last shown
    state = player['state']

    # Handle input
    if GameStates.states[state].key?('textEntry')
      text_entry_key = GameStates.states[state]['textEntry']['key']
      puts "Player #{player} State #{state} adding text Key #{text_entry_key} value #{body}"
      player[text_entry_key] = String.new(body)
    end

    ## State transition

    if params.key?('SkipToState')
      state = params['SkipToState']
    elsif GameStates.states[state].key?('selection')
      # handle using the input to choose selection
      if (index = body.to_i) != 0
        selections = GameStates.states[state]['selection'].to_a
        if selections.length >= index
          state = selections[index - 1].last
        else
          puts "selections.length #{selections.length} index #{index}"
          puts "Player selected #{body} but selections are #{selections}"
        end
      else
Joe Libipl's avatar
typo    
Joe Libipl committed
87
        puts "Player gave non-numeric selection: #{body}"
Joe Libipl's avatar
Joe Libipl committed
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
      end
    elsif GameStates.states[state].key?('next')
      state = GameStates.states[state]['next']
    else
      puts "Not sure where to go from state: #{GameStates.states[state]}"
    end

    ## Now state is the state to be shown
    player['state'] = state

    player
  end

  def process_output(player)
    state = player['state']

    response = GameStates.story(state) + GameStates.selections(state)

    # Fill in values in response
    player.keys.each do |key|
      puts "Filling in key #{key}"
      response.gsub!(":#{key}:", player[key])
    end

    response
  end

  get '/' do
    source = params['From']

    if player_data.key?(source)
      puts "Player #{source} has data #{player_data[source]}"
      player_data[source] = process_input(params, player_data[source])
    else
      puts "Player #{source} is a new player!"
      player_data[source] = {}
      player_data[source]['state'] = params['SkipToState'] || 'SPLASH'
    end

    response = process_output(player_data[source])

    response
  end

  run! if app_file == $PROGRAM_NAME
end