@Override
  public void onPaint(Graphics2D graphics2D) {
    this.runtimeMillis = System.currentTimeMillis() - this.startTimeMillis;
    graphics2D.setColor(new Color(0, 0, 100, 120));
    graphics2D.fillRect(25, 240, 350, 82);

    graphics2D.setColor(Color.GREEN);
    graphics2D.fillRect(25, 240, 3 * this.expTracker.getPercentageToNextLevel(Skill.HERBLORE), 9);

    graphics2D.setColor(Color.WHITE);
    graphics2D.drawRect(25, 240, 350, 9);
    graphics2D.drawRect(25, 240, 350, 82);

    int cleanedPerHour =
        (int)
            (3600000.0
                / (double) (System.currentTimeMillis() - this.startTimeMillis)
                * (double) this.herbsCleaned);
    String profitsPerHour =
        String.valueOf(cleanedPerHour * this.profitPerClean)
            .replaceAll("(\\d)(?=(\\d{3})+$)", "$1,");

    graphics2D.setFont(new Font("Monospaced", 0, 12));
    graphics2D.drawString(
        "Herbs cleaned: " + this.herbsCleaned + " | (" + cleanedPerHour + ")", 28, 260);
    graphics2D.drawString("Current State: " + this.textualState, 28, 270);
    graphics2D.drawString("Time running: " + Core.formatElapsedTime(this.runtimeMillis), 28, 280);
    graphics2D.drawString(
        "XP Gained: "
            + this.expTracker.getExperienceGained(Skill.HERBLORE)
            + (" | (" + this.expTracker.getLevelsGained(Skill.HERBLORE) + ")"),
        28,
        290);
    graphics2D.drawString(
        "XP/hr: "
            + this.expTracker.gainedPerHour(Skill.HERBLORE)
            + " | Profit/hr: "
            + profitsPerHour,
        28,
        300);
    graphics2D.drawString(
        "Time till next level: "
            + Core.formatElapsedTime(this.expTracker.timeUntilNextLevel(Skill.HERBLORE)),
        28,
        310);

    graphics2D.drawLine(
        (int) this.getMouse().getPosition().getX(),
        (int) this.getMouse().getPosition().getY() + 10,
        (int) this.getMouse().getPosition().getX(),
        (int) this.getMouse().getPosition().getY() - 10);
    graphics2D.drawLine(
        (int) this.getMouse().getPosition().getX() + 10,
        (int) this.getMouse().getPosition().getY(),
        (int) this.getMouse().getPosition().getX() - 10,
        (int) this.getMouse().getPosition().getY());

    graphics2D.setColor(Color.RED);
    graphics2D.drawString("by Chicken Wing      v1.0", 70, 320);
  }
  @Override
  public void onStart() {
    if (!this.widgets.get(548, 61).isVisible()) {
      this.widgets.get(548, 48).interact();
    }

    getBot().addMouseListener(new RetardMouseListener(this));
    this.expTracker = new ExperienceTracker(this);
    expTracker.startTracking(Skill.HERBLORE);
    EventQueue.invokeLater(this::initializeUI);

    this.cleanPattern = this.mainFrame.getCleanPattern();
    this.selectedHerb = this.mainFrame.getSelectedHerb();
    log(selectedHerb + " " + this.selectedHerb.getGrimyName());
    this.cleanHerbName = this.selectedHerb.getCleanName();
    this.grimyHerbName = this.selectedHerb.getGrimyName();
    this.cleanDelay = this.mainFrame.getCleanDelay();
    log("Delay set: " + this.cleanDelay + "ms");

    String textualPattern = "";
    for (int i = 0; i < cleanPattern.length; i++) {
      textualPattern += i;
      textualPattern += " ";
      textualPattern += cleanPattern[i];
    }
    log("Pattern: " + textualPattern);

    this.startTimeMillis = System.currentTimeMillis();

    Collections.addAll(
        states,
        new OpenBankState(this),
        new CloseBankState(this),
        new DepositItemsState(this),
        new CleanHerbsState(this),
        new WithdrawItemsState(this),
        new LogoutState(this));

    this.mainFrame.dispose();

    try {
      this.cleanHerbPrice = PriceAPI.getSellingPrice(this.selectedHerb.getCleanId());
      this.grimyHerbPrice = PriceAPI.getBuyingPrice(this.selectedHerb.getGrimyId());
    } catch (IOException e1) {
      e1.printStackTrace();
      this.cleanHerbPrice = 0;
    }

    this.profitPerClean = this.cleanHerbPrice - this.grimyHerbPrice;
    new HerbsCleanedItemTracker(this).start();
  }