Class: AcpcTableManager::AcpcProxy

Inherits:
Object
  • Object
show all
Includes:
ProxyUtils, SimpleLogging
Defined in:
lib/acpc_table_manager/acpc_proxy.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ProxyUtils

all_in, amount_to_call, betting_sequence, chip_contribution_after_calling, chip_contributions_in_previous_rounds, #exit_and_del_saved, minimum_wager_to, opponents, #play_check_fold!, players, players_at_the_table_to_json, pot_after_call, pot_at_start_of_round, pot_fraction_wager_to_over_round, #start_proxy

Methods included from SimpleLogging

#log, #log_with, #logger

Constructor Details

#initialize(id, game) ⇒ AcpcProxy

Returns a new instance of AcpcProxy.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 12

def initialize(id, game)
  @game = game
  @id = id
  @game_info = AcpcTableManager.exhibition_config.games[game]
  unless @game_info
    raise OptionParser::ArgumentError.new(
      "\"#{game}\" is not a recognized game. Registered games: #{AcpcTableManager.exhibition_config.games.keys}."
    )
  end

  @logger = AcpcTableManager.new_log(
    "#{id}.log",
    File.join(AcpcTableManager.config.log_directory, 'proxies')
  )

  @communicator = AcpcTableManager::ProxyCommunicator.new(id)
  @communicator.del_saved # Clear stale messages to avoid unpredictable behaviour
  @state_index = 0
  @last_message_received = Time.now
end

Instance Attribute Details

#gameObject (readonly)

Returns the value of attribute game.



10
11
12
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 10

def game
  @game
end

#game_infoObject (readonly)

Returns the value of attribute game_info.



10
11
12
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 10

def game_info
  @game_info
end

#idObject (readonly)

Returns the value of attribute id.



10
11
12
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 10

def id
  @id
end

#last_message_receivedObject (readonly)

Returns the value of attribute last_message_received.



10
11
12
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 10

def last_message_received
  @last_message_received
end

#state_indexObject (readonly)

Returns the value of attribute state_index.



10
11
12
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 10

def state_index
  @state_index
end

Instance Method Details

#act(action) ⇒ Object



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
87
88
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 53

def act(action)
  if action == 'next-hand'
    @proxy.next_hand! do |patt|
      log 'next_hand! block', match_state: patt.match_state.to_s
      @communicator.publish(
        AcpcTableManager::ProxyUtils.players_at_the_table_to_json(
          patt,
          num_hands_per_match,
          @state_index
        )
      )
      @state_index += 1
    end

    log(
      'after next_hand!',
      users_turn_to_act?: @proxy.users_turn_to_act?,
      match_over?: match_over?
    )
  else
    log 'before play', users_turn_to_act?: @proxy.users_turn_to_act?,
                       action: action

    if @proxy.users_turn_to_act?
      play action

      log(
        'after play',
        users_turn_to_act?: @proxy.users_turn_to_act?,
        match_over?: match_over?
      )
    else
      log 'skipped play'
    end
  end
end

#action_timeout_reachedObject



120
121
122
123
124
125
126
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 120

def action_timeout_reached
  AcpcTableManager.config.proxy_timeout_s && (
    Time.now > (
      @last_message_received + AcpcTableManager.config.proxy_timeout_s
    )
  )
end

#match_over?Boolean

Returns:

  • (Boolean)


90
91
92
93
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 90

def match_over?
  @proxy.match_ended?(num_hands_per_match) ||
  !@proxy.connected?
end

#message_loopObject



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 95

def message_loop
  @communicator.subscribe_with_timeout do |data|
    log __method__, data: data

    if data['resend']
      log __method__, msg: 'Resending match state'
      @communicator.publish(
        AcpcTableManager::ProxyUtils.players_at_the_table_to_json(
          @proxy,
          num_hands_per_match,
          @state_index
        )
      )
      @state_index += 1
    elsif data['kill']
      log __method__, msg: 'Exiting'
      exit_and_del_saved
    else
      act data['action']
    end
    exit_and_del_saved if match_over?
    @last_message_received = Time.now
  end
end

#must_send_readyObject



33
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 33

def must_send_ready() AcpcTableManager.config.must_send_ready end

#num_hands_per_matchObject



35
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 35

def num_hands_per_match() @game_info['num_hands_per_match'] end

#play(action) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 37

def play(action)
  action = PokerAction.new(action) unless action.is_a?(PokerAction)

  @proxy.play!(action) do |patt|
    log 'play! block', match_state: patt.match_state.to_s
    @communicator.publish(
      AcpcTableManager::ProxyUtils.players_at_the_table_to_json(
        patt,
        num_hands_per_match,
        @state_index
      )
    )
    @state_index += 1
  end
end

#start(seat, port) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/acpc_table_manager/acpc_proxy.rb', line 128

def start(seat, port)
  begin
    log(
      __method__,
      id: @id,
      game: @game,
      seat: seat,
      port: port,
      version: AcpcTableManager::VERSION,
      send_channel: @communicator.send_channel,
      receive_channel: @communicator.receive_channel,
      must_send_ready: must_send_ready
    )

    @proxy = start_proxy(
      @game_info,
      seat,
      port,
      must_send_ready
    ) do |patt|
      log 'start_proxy_block', match_state: patt.match_state.to_s
      @communicator.publish(
        AcpcTableManager::ProxyUtils.players_at_the_table_to_json(
          patt,
          num_hands_per_match,
          @state_index
        )
      )
      @state_index += 1
    end

    log 'starting event loop'

    loop do
      begin
        message_loop
      rescue AcpcTableManager::SubscribeTimeout
        match_is_over = match_over?

        log(
          'subscription timeout reached',
          {
            match_over?: match_is_over,
            users_turn_to_act?: @proxy.users_turn_to_act?,
            action_timeout_reached: action_timeout_reached,
            on_proxy_timeout: AcpcTableManager.config.on_proxy_timeout
          }
        )
        if match_is_over
          exit_and_del_saved
        elsif !@proxy.users_turn_to_act?
          @last_message_received = Time.now
        elsif action_timeout_reached
          if AcpcTableManager.config.on_proxy_timeout == 'fold'
            play_check_fold! @proxy
          else
            exit_and_del_saved
          end
        end
      end
    end
  rescue => e
    log(
      __method__,
      {
        id: @id,
        message: e.message,
        backtrace: e.backtrace
      },
      Logger::Severity::ERROR
    )
    AcpcTableManager.notify e # Send an email notification
  end
  exit_and_del_saved
end