class RingInstance extends AbstractInstance {
  private static final String INSTANCE = "Instance ";

  /**
   * Constructor of RingInstance.
   */
  public RingInstance(MessageManager messageManager, int localId, int leaderId) {
    super(messageManager, localId, leaderId);
  }

  /**
   * Process the heartbeat invoke message. After receiving the message, the instance will send a
   * heartbeat to leader to check its health. If alive, it will inform the next instance to do the
   * heartbeat. If not, it will start the election process.
   */
  @Override
  protected void handleHeartbeatInvokeMessage() {
    try {
      var isLeaderAlive = messageManager.sendHeartbeatMessage(this.leaderId);
      if (isLeaderAlive) {
        LOGGER.info(INSTANCE + localId + "- Leader is alive. Start next heartbeat in 5 second.");
        Thread.sleep(HEARTBEAT_INTERVAL);
        messageManager.sendHeartbeatInvokeMessage(this.localId);
      } else {
        LOGGER.info(INSTANCE + localId + "- Leader is not alive. Start election.");
        messageManager.sendElectionMessage(this.localId, String.valueOf(this.localId));
      }
    } catch (InterruptedException e) {
      LOGGER.info(INSTANCE + localId + "- Interrupted.");
    }
  }

  /**
   * Process election message. If the local ID is contained in the ID list, the instance will select
   * the alive instance with smallest ID to be the new leader, and send the leader inform message.
   * If not, it will add its local ID to the list and send the message to the next instance in the
   * ring.
   */
  @Override
  protected void handleElectionMessage(Message message) {<FILL_FUNCTION_BODY>}

  /**
   * Process leader Message. The instance will set the leader ID to be the new one and send the
   * message to the next instance until all the alive instance in the ring is informed.
   */
  @Override
  protected void handleLeaderMessage(Message message) {
    var newLeaderId = Integer.valueOf(message.getContent());
    if (this.leaderId != newLeaderId) {
      LOGGER.info(INSTANCE + localId + " - Update leaderID");
      this.leaderId = newLeaderId;
      messageManager.sendLeaderMessage(localId, newLeaderId);
    } else {
      LOGGER.info(INSTANCE + localId + " - Leader update done. Start heartbeat.");
      messageManager.sendHeartbeatInvokeMessage(localId);
    }
  }

  /**
   * Not used in Ring instance.
   */
  @Override
  protected void handleLeaderInvokeMessage() {
    // Not used in Ring instance.
  }

  @Override
  protected void handleHeartbeatMessage(Message message) {
    // Not used in Ring instance.
  }

  @Override
  protected void handleElectionInvokeMessage() {
    // Not used in Ring instance.
  }

}

    var content = message.getContent();
    LOGGER.info(INSTANCE + localId + " - Election Message: " + content);
    var candidateList = Arrays.stream(content.trim().split(","))
        .map(Integer::valueOf)
        .sorted()
        .toList();
    if (candidateList.contains(localId)) {
      var newLeaderId = candidateList.get(0);
      LOGGER.info(INSTANCE + localId + " - New leader should be " + newLeaderId + ".");
      messageManager.sendLeaderMessage(localId, newLeaderId);
    } else {
      content += "," + localId;
      messageManager.sendElectionMessage(localId, content);
    }
  
<methods>public void <init>(com.iluwatar.leaderelection.MessageManager, int, int) ,public boolean isAlive() ,public void onMessage(com.iluwatar.leaderelection.Message) ,public void run() ,public void setAlive(boolean) <variables>protected static final int HEARTBEAT_INTERVAL,private static final java.lang.String INSTANCE,protected boolean alive,protected int leaderId,protected final non-sealed int localId,protected com.iluwatar.leaderelection.MessageManager messageManager,protected Queue<com.iluwatar.leaderelection.Message> messageQueue