code: def _parse_memory(self, client, ident, last_obs):
      mem = client.memory
      n = len(mem)
  
      # debug info
      if ident == 1:
          for i, exp in enumerate(mem):
              logger.info(
                  "[step:{}] obs:{} action:{} reward:{} shaping_reward:{}".format(
                      i,
                      np.sum(mem[i].obs),
                      np.sum(mem[i].action),
                      mem[i].reward,
                      mem[i].info["shaping_reward"],
                  )
              )
  
      episode_rpm = []
      for i in range(n - 1):
          if not mem[i].info["target_changed"]:
              episode_rpm.append(
                  [
                      mem[i].obs,
                      mem[i].action,
                      mem[i].info["shaping_reward"],
                      mem[i + 1].obs,
                      False,
                      mem[i].info["target_change_times"],
                  ]
              )
      if not mem[-1].info["target_changed"]:
          episode_rpm.append(
              [
                  mem[-1].obs,
                  mem[-1].action,
                  mem[-1].info["shaping_reward"],
                  last_obs,
                  not mem[-1].info["timeout"],
                  mem[i].info["target_change_times"],
              ]
          )
  
      indicators_dict = calc_indicators(mem)
      indicators_dict[
          "free_client_num"
      ] = self.ready_client_queue.qsize()
      indicators_dict["noiselevel"] = self.noiselevel
  
      with self.MEMORY_LOCK:
          self.add_episode_rpm(episode_rpm)
          self.scalars_manager.record(indicators_dict, self.global_step)
          self.global_step += 1
          if self.global_step >= 50:
              self.noiselevel = self.noiselevel * NOISE_DECAY
  
      client.reset()
  
imports: import grpc
  import json
  import numpy
  import os
  import queue
  import simulator_pb2
  import simulator_pb2_grpc
  import six
  import time
  import threading
  from args import get_server_args
  from collections import defaultdict
  from concurrent import futures
  from multi_head_ddpg import MultiHeadDDPG
  from opensim_agent import OpenSimAgent
  from opensim_model import OpenSimModel
  from parl.utils import logger
  from replay_memory import ReplayMemory
  from utils import calc_indicators, ScalarsManager, TransitionExperience
label_desc: Use image node_id 5 for calling the SimulatorServer obj's underlying member method code with example usage: obj._parse_memory(client, ident, last_obs) without return types