text: import asyncio
  import socketio
  
  # hack into python's low level event loop to inherit its asynchronous black magic abilities.
  loop = asyncio.get_event_loop()
  
  
  class SocketCommunicationManager:
      # this manager allows communication for a 3rd part IDE with either the unity editor or the CoderZ website.
  
      def __init__(self, configuration):
          # save a copy of the configuration for later use.
          self.__configuration = configuration
  
          # asyncio black magic variables to be able to work asynchronously while
          # the end-user gets a synchronous experience.
          self.__event = asyncio.Event()
          self.__event.set()
          self.__socket_response = None
  
          # create a socket connection to the robot.
          self.__sio = socketio.AsyncClient()
          loop.run_until_complete(
              self.__sio.connect(configuration["server_url"]))
  
          # if a token authentication is required, authenticate.
          if configuration["use_authentication_token"]:
              loop.run_until_complete(self.__authenticate_with_token())
  
          # a function that is triggered whenever there is a response from the robot.
          @self.__sio.on(self.__configuration["socket_on_route"])
          def on_message(data):
              # when receiving a message, get the response
              # data and set the event to release the waiting on the request sending function.
              self.__socket_response = data
              self.__event.set()
  
      # general request function to communicate with the robot.
      def send_request(self, request_object, should_wait_for_answer):
          # if the method returns value:
          if should_wait_for_answer is not None:
              res = loop.run_until_complete(
                  self.__send_request_and_wait_for_response(request_object))
              return res["result"]
          # if it doesn't return a value:
          else:
              loop.run_until_complete(self.__send_command(request_object))
              return None
  
      async def __authenticate_with_token(self):
          # validate the socket io connection to the server using a token.
  
          # ask for a token string from the user.
          token = input(
              "Please insert the token generated by the CoderZ website: ")
  
          # an event object for async usage
          event = asyncio.Event()
  
          # prepare a catch function for a response from the server regarding the status of the authentication.
          @self.__sio.on('token validation')
          def on_message(data):
              if data["status"]:
                  event.set()
              else:
                  raise Exception('token authentication failed')
  
          # send an authentication request.
          await self.__sio.emit('authenticate IDE', data={"token": token})
          # wait for a response.
          await event.wait()
  
      async def wait_for_game_start_message(self):
          # wait until the game start before running any code
  
          # an event object for async usage
          event = asyncio.Event()
  
          # prepare a catch function for a game ready message from the server.
          @self.__sio.on('run code IDE')
          def on_message():
              event.set()
  
          # wait for a response.
          await event.wait()
  
      # send a request for data from the robot.
      async def __send_request_and_wait_for_response(self, request_object):
          # clear the event variable to open up for later responses.
          self.__event.clear()
  
          # emit the request and wait for a response(A.K.A a self.__event.set() somewhere in the code)
          await self.__sio.emit(self.__configuration["socket_emit_route"], data=request_object)
          await self.__event.wait()
  
          # return the response.
          return self.__socket_response
  
      # send a command to the robot which isn't supposed to return data
      async def __send_command(self, request_object):
          # emit the command.
          await self.__sio.emit(self.__configuration["socket_emit_route"], data=request_object)
          # for some weird reason, we need to wait an arbitrarily
          # small amount of time in order for the emit to work.
          # TODO: figure out why...
          await asyncio.sleep(0.000001)
  
      def get_configurations(self):
          return self.__configuration
  