class_docstr: A Process that pulls replays and processes them.
docstr: Process a single replay, updating the stats.
docstr_tok: ["Process","a","single","replay",",","updating","the","stats","."]
code: def process_replay(
      self, controller, replay_data, map_data, player_id
  ):
      """Process a single replay, updating the stats."""
      self._update_stage("start_replay")
      controller.start_replay(
          sc_pb.RequestStartReplay(
              replay_data=replay_data,
              map_data=map_data,
              options=interface,
              observed_player_id=player_id,
          )
      )
  
      feat = features.features_from_game_info(controller.game_info())
  
      self.stats.replay_stats.replays += 1
      self._update_stage("step")
      controller.step()
      while True:
          self.stats.replay_stats.steps += 1
          self._update_stage("observe")
          obs = controller.observe()
  
          for action in obs.actions:
              act_fl = action.action_feature_layer
              if act_fl.HasField("unit_command"):
                  self.stats.replay_stats.made_abilities[
                      act_fl.unit_command.ability_id
                  ] += 1
              if act_fl.HasField("camera_move"):
                  self.stats.replay_stats.camera_move += 1
              if act_fl.HasField("unit_selection_point"):
                  self.stats.replay_stats.select_pt += 1
              if act_fl.HasField("unit_selection_rect"):
                  self.stats.replay_stats.select_rect += 1
              if action.action_ui.HasField("control_group"):
                  self.stats.replay_stats.control_group += 1
  
              try:
                  func = feat.reverse_action(action).function
              except ValueError:
                  func = -1
              self.stats.replay_stats.made_actions[func] += 1
  
          for valid in obs.observation.abilities:
              self.stats.replay_stats.valid_abilities[
                  valid.ability_id
              ] += 1
  
          for u in obs.observation.raw_data.units:
              self.stats.replay_stats.unit_ids[u.unit_type] += 1
              for b in u.buff_ids:
                  self.stats.replay_stats.buffs[b] += 1
  
          for u in obs.observation.raw_data.player.upgrade_ids:
              self.stats.replay_stats.upgrades[u] += 1
  
          for e in obs.observation.raw_data.effects:
              self.stats.replay_stats.effects[e.effect_id] += 1
  
          for ability_id in feat.available_actions(obs.observation):
              self.stats.replay_stats.valid_actions[ability_id] += 1
  
          if obs.player_result:
              break
  
          self._update_stage("step")
          controller.step(FLAGS.step_mul)
  
imports: import collections
  import multiprocessing
  import os
  import queue
  import signal
  import sys
  import threading
  import time
  from absl import app
  from absl import flags
  from pysc2 import run_configs
  from pysc2.lib import features
  from pysc2.lib import point
  from pysc2.lib import protocol
  from pysc2.lib import remote_controller
  from pysc2.lib import replay
  from pysc2.lib import static_data
  from pysc2.lib import gfile
  from s2clientprotocol import common_pb2
  from s2clientprotocol import sc2api_pb2
label_desc: Use image node_id 5 for calling the ReplayProcessor obj's underlying member method code with example usage: obj.process_replay(controller, replay_data, map_data, player_id) without return types