@Override
  public final boolean checkDefaulted() {
    try {
      SystemMessage reason = null;
      Participant par;
      for (int i = _teamOneSize; --i >= 0; ) {
        par = _teamOne[i];
        par.updatePlayer();
        reason = checkDefaulted(par.getPlayer());
        if (reason != null) {
          par.setDefaulted(true);
          if (!_teamOneDefaulted) {
            _teamOneDefaulted = true;
            for (Participant t : _teamTwo) {
              if (t.getPlayer() != null) {
                t.getPlayer().sendPacket(reason);
              }
            }
          }
        }
      }

      for (int i = _teamTwoSize; --i >= 0; ) {
        par = _teamTwo[i];
        par.updatePlayer();
        reason = checkDefaulted(par.getPlayer());
        if (reason != null) {
          par.setDefaulted(true);
          if (!_teamTwoDefaulted) {
            _teamTwoDefaulted = true;
            for (Participant t : _teamOne) {
              if (t.getPlayer() != null) {
                t.getPlayer().sendPacket(reason);
              }
            }
          }
        }
      }

      return _teamOneDefaulted || _teamTwoDefaulted;
    } catch (Exception e) {
      _log.log(Level.WARNING, "Exception on checkDefaulted(): " + e.getMessage(), e);
      return true;
    }
  }
  @Override
  protected final void broadcastPacket(L2GameServerPacket packet) {
    Participant par;
    for (int i = 0; i < _teamOneSize; i++) {
      par = _teamOne[i];
      if (par.updatePlayer()) {
        par.getPlayer().sendPacket(packet);
      }
    }

    for (int i = 0; i < _teamTwoSize; i++) {
      par = _teamTwo[i];
      par.updatePlayer();
      if (par.getPlayer() != null) {
        par.getPlayer().sendPacket(packet);
      }
    }
  }
  @Override
  protected void validateWinner(L2OlympiadStadiumZone stadium) {
    if (_aborted) {
      return;
    }

    ExOlympiadMatchResult result = null;

    boolean tie = false;
    int winside = 0;

    List<OlympiadInfo> list1 = new ArrayList<>(3);
    List<OlympiadInfo> list2 = new ArrayList<>(3);

    final boolean tOneCrash = teamOneAllDisconnected();
    final boolean tTwoCrash = teamTwoAllDisconnected();

    Participant par;
    SystemMessage sm;
    int points;

    // Check for if a team defaulted before battle started
    if (_teamOneDefaulted || _teamTwoDefaulted) {
      try {
        if (_teamOneDefaulted) {
          for (int i = _teamOneSize; --i >= 0; ) {
            par = _teamOne[i];
            points = par.getStats().getInt(POINTS) / getDivider();
            int val = Math.min(par.getStats().getInt(POINTS) / 3, Config.ALT_OLY_MAX_POINTS);
            removePointsFromParticipant(par, val);
            list1.add(
                new OlympiadInfo(
                    par.getName(),
                    par.getClanName(),
                    par.getClanId(),
                    par.getBaseClass(),
                    _damageT1,
                    points - val,
                    -val));
          }
          winside = 2;
        }
        if (_teamTwoDefaulted) {
          for (int i = _teamTwoSize; --i >= 0; ) {
            par = _teamTwo[i];
            points = par.getStats().getInt(POINTS) / getDivider();
            int val = Math.min(par.getStats().getInt(POINTS) / 3, Config.ALT_OLY_MAX_POINTS);
            removePointsFromParticipant(par, val);
            list2.add(
                new OlympiadInfo(
                    par.getName(),
                    par.getClanName(),
                    par.getClanId(),
                    par.getBaseClass(),
                    _damageT2,
                    points - val,
                    -val));
          }
          if (winside == 2) {
            tie = true;
          } else {
            winside = 1;
          }
        }
        if (winside == 1) {
          result = new ExOlympiadMatchResult(tie, winside, list1, list2);
        } else {
          result = new ExOlympiadMatchResult(tie, winside, list2, list1);
        }
        stadium.broadcastPacket(result);
      } catch (Exception e) {
        _log.log(Level.WARNING, "Exception on validateWinner(): " + e.getMessage(), e);
      }
      return;
    }

    // points to be dedicted in case of losing
    final int[] pointsTeamOne = new int[_teamOneSize];
    final int[] pointsTeamTwo = new int[_teamTwoSize];
    final int[] maxPointsTeamOne = new int[_teamOneSize];
    final int[] maxPointsTeamTwo = new int[_teamTwoSize];
    int totalPointsTeamOne = 0;
    int totalPointsTeamTwo = 0;
    for (int i = 0; i < _teamOneSize; i++) {
      points = _teamOne[i].getStats().getInt(POINTS) / getDivider();
      if (points <= 0) {
        points = 1;
      } else if (points > Config.ALT_OLY_MAX_POINTS) {
        points = Config.ALT_OLY_MAX_POINTS;
      }

      totalPointsTeamOne += points;
      pointsTeamOne[i] = points;
      maxPointsTeamOne[i] = points;
    }

    for (int i = _teamTwoSize; --i >= 0; ) {
      points = _teamTwo[i].getStats().getInt(POINTS) / getDivider();
      if (points <= 0) {
        points = 1;
      } else if (points > Config.ALT_OLY_MAX_POINTS) {
        points = Config.ALT_OLY_MAX_POINTS;
      }

      totalPointsTeamTwo += points;
      pointsTeamTwo[i] = points;
      maxPointsTeamTwo[i] = points;
    }

    // Choose minimum sum
    int min = Math.min(totalPointsTeamOne, totalPointsTeamTwo);

    // make sure all team members got same number of the points: round down to 3x
    min = (min / MAX_TEAM_SIZE) * MAX_TEAM_SIZE;

    // calculating coefficients and trying to correct total number of points for each team
    // due to rounding errors total points after correction will always be lower or equal
    // than needed minimal sum
    final double dividerOne = (double) totalPointsTeamOne / min;
    final double dividerTwo = (double) totalPointsTeamTwo / min;
    totalPointsTeamOne = min;
    totalPointsTeamTwo = min;
    for (int i = 0; i < _teamOneSize; i++) {
      points = Math.max((int) (pointsTeamOne[i] / dividerOne), 1);
      pointsTeamOne[i] = points;
      totalPointsTeamOne -= points;
    }

    for (int i = _teamTwoSize; --i >= 0; ) {
      points = Math.max((int) (pointsTeamTwo[i] / dividerTwo), 1);
      pointsTeamTwo[i] = points;
      totalPointsTeamTwo -= points;
    }

    // compensating remaining points, first team from begin to end, second from end to begin
    for (int i = 0; (totalPointsTeamOne > 0) && (i < _teamOneSize); i++) {
      if (pointsTeamOne[i] < maxPointsTeamOne[i]) {
        pointsTeamOne[i]++;
        totalPointsTeamOne--;
      }
    }

    for (int i = _teamTwoSize; (totalPointsTeamTwo > 0) && (--i >= 0); ) {
      if (pointsTeamTwo[i] < maxPointsTeamTwo[i]) {
        pointsTeamTwo[i]++;
        totalPointsTeamTwo--;
      }
    }

    // Create results for players if a team crashed
    if (tOneCrash || tTwoCrash) {
      try {
        if (tTwoCrash && !tOneCrash) {
          sm = SystemMessage.getSystemMessage(SystemMessageId.CONGRATULATIONS_C1_YOU_WIN_THE_MATCH);
          sm.addString(_teamOne[0].getName());
          stadium.broadcastPacket(sm);

          for (int i = 0; i < _teamTwoSize; i++) {
            par = _teamTwo[i];
            par.updateStat(COMP_LOST, 1);
            points = pointsTeamTwo[i];
            removePointsFromParticipant(par, points);
            list2.add(
                new OlympiadInfo(
                    par.getName(),
                    par.getClanName(),
                    par.getClanId(),
                    par.getBaseClass(),
                    _damageT2,
                    par.getStats().getInt(POINTS) - points,
                    -points));
          }

          points = min / MAX_TEAM_SIZE;
          for (int i = 0; i < _teamOneSize; i++) {
            par = _teamOne[i];
            par.updateStat(COMP_WON, 1);
            addPointsToParticipant(par, points);
            list1.add(
                new OlympiadInfo(
                    par.getName(),
                    par.getClanName(),
                    par.getClanId(),
                    par.getBaseClass(),
                    _damageT1,
                    par.getStats().getInt(POINTS) + points,
                    points));
          }

          for (int i = 0; i < _teamOneSize; i++) {
            rewardParticipant(_teamOne[i].getPlayer(), getReward());
          }

          winside = 1;
        } else if (tOneCrash && !tTwoCrash) {
          sm = SystemMessage.getSystemMessage(SystemMessageId.CONGRATULATIONS_C1_YOU_WIN_THE_MATCH);
          sm.addString(_teamTwo[0].getName());
          stadium.broadcastPacket(sm);

          for (int i = 0; i < _teamOneSize; i++) {
            par = _teamOne[i];
            par.updateStat(COMP_LOST, 1);
            points = pointsTeamOne[i];
            removePointsFromParticipant(par, points);
            list1.add(
                new OlympiadInfo(
                    par.getName(),
                    par.getClanName(),
                    par.getClanId(),
                    par.getBaseClass(),
                    _damageT1,
                    par.getStats().getInt(POINTS) - points,
                    -points));
          }

          points = min / MAX_TEAM_SIZE;
          for (int i = 0; i < _teamTwoSize; i++) {
            par = _teamTwo[i];
            par.updateStat(COMP_WON, 1);
            addPointsToParticipant(par, points);
            list2.add(
                new OlympiadInfo(
                    par.getName(),
                    par.getClanName(),
                    par.getClanId(),
                    par.getBaseClass(),
                    _damageT2,
                    par.getStats().getInt(POINTS) + points,
                    points));
          }

          winside = 2;

          for (int i = 0; i < _teamTwoSize; i++) {
            rewardParticipant(_teamTwo[i].getPlayer(), getReward());
          }
        } else if (tOneCrash && tTwoCrash) {
          stadium.broadcastPacket(
              SystemMessage.getSystemMessage(
                  SystemMessageId.THERE_IS_NO_VICTOR_THE_MATCH_ENDS_IN_A_TIE));

          for (int i = _teamOneSize; --i >= 0; ) {
            par = _teamOne[i];
            par.updateStat(COMP_LOST, 1);
            removePointsFromParticipant(par, pointsTeamOne[i]);
            list1.add(
                new OlympiadInfo(
                    par.getName(),
                    par.getClanName(),
                    par.getClanId(),
                    par.getBaseClass(),
                    _damageT1,
                    par.getStats().getInt(POINTS) - pointsTeamOne[i],
                    -pointsTeamOne[i]));
          }

          for (int i = _teamTwoSize; --i >= 0; ) {
            par = _teamTwo[i];
            par.updateStat(COMP_LOST, 1);
            removePointsFromParticipant(par, pointsTeamTwo[i]);
            list2.add(
                new OlympiadInfo(
                    par.getName(),
                    par.getClanName(),
                    par.getClanId(),
                    par.getBaseClass(),
                    _damageT2,
                    par.getStats().getInt(POINTS) - pointsTeamOne[i],
                    -pointsTeamOne[i]));
          }

          tie = true;
        }

        for (int i = _teamOneSize; --i >= 0; ) {
          par = _teamOne[i];
          par.updateStat(COMP_DONE, 1);
          par.updateStat(COMP_DONE_WEEK, 1);
          par.updateStat(getWeeklyMatchType(), 1);
        }

        for (int i = _teamTwoSize; --i >= 0; ) {
          par = _teamTwo[i];
          par.updateStat(COMP_DONE, 1);
          par.updateStat(COMP_DONE_WEEK, 1);
          par.updateStat(getWeeklyMatchType(), 1);
        }
      } catch (Exception e) {
        _log.log(Level.WARNING, "Exception on validateWinner(): " + e.getMessage(), e);
      }

      if (winside == 1) {
        result = new ExOlympiadMatchResult(tie, winside, list1, list2);
      } else {
        result = new ExOlympiadMatchResult(tie, winside, list2, list1);
      }
      stadium.broadcastPacket(result);
      return;
    }

    try {
      double hp;
      double teamOneHp = 0;
      double teamTwoHp = 0;

      for (int i = _teamOneSize; --i >= 0; ) {
        par = _teamOne[i];
        if (!par.isDisconnected() && (par.getPlayer() != null) && !par.getPlayer().isDead()) {
          hp = par.getPlayer().getCurrentHp() + par.getPlayer().getCurrentCp();
          if (hp >= 0.5) {
            teamOneHp += hp;
          }
        }
        par.updatePlayer();
      }

      for (int i = _teamTwoSize; --i >= 0; ) {
        par = _teamTwo[i];
        if (!par.isDisconnected() && (par.getPlayer() != null) && !par.getPlayer().isDead()) {
          hp = par.getPlayer().getCurrentHp() + par.getPlayer().getCurrentCp();
          if (hp >= 0.5) {
            teamTwoHp += hp;
          }
        }
        par.updatePlayer();
      }

      if (((teamTwoHp == 0) && (teamOneHp != 0))
          || ((_damageT1 > _damageT2) && (teamTwoHp != 0) && (teamOneHp != 0))) {
        sm = SystemMessage.getSystemMessage(SystemMessageId.CONGRATULATIONS_C1_YOU_WIN_THE_MATCH);
        sm.addString(_teamOne[0].getName());
        stadium.broadcastPacket(sm);

        for (int i = 0; i < _teamTwoSize; i++) {
          par = _teamTwo[i];
          par.updateStat(COMP_LOST, 1);
          points = pointsTeamTwo[i];
          removePointsFromParticipant(par, points);
          list2.add(
              new OlympiadInfo(
                  par.getName(),
                  par.getClanName(),
                  par.getClanId(),
                  par.getBaseClass(),
                  _damageT2,
                  par.getStats().getInt(POINTS) - points,
                  -points));
        }

        points = min / MAX_TEAM_SIZE;
        for (int i = 0; i < _teamOneSize; i++) {
          par = _teamOne[i];
          par.updateStat(COMP_WON, 1);
          addPointsToParticipant(par, points);
          list1.add(
              new OlympiadInfo(
                  par.getName(),
                  par.getClanName(),
                  par.getClanId(),
                  par.getBaseClass(),
                  _damageT1,
                  par.getStats().getInt(POINTS) + points,
                  points));
        }

        winside = 1;

        for (int i = 0; i < _teamOneSize; i++) {
          rewardParticipant(_teamOne[i].getPlayer(), getReward());
        }
      } else if (((teamOneHp == 0) && (teamTwoHp != 0))
          || ((_damageT2 > _damageT1) && (teamOneHp != 0) && (teamTwoHp != 0))) {
        sm = SystemMessage.getSystemMessage(SystemMessageId.CONGRATULATIONS_C1_YOU_WIN_THE_MATCH);
        sm.addString(_teamTwo[0].getName());
        stadium.broadcastPacket(sm);

        for (int i = 0; i < _teamOneSize; i++) {
          par = _teamOne[i];
          par.updateStat(COMP_LOST, 1);
          points = pointsTeamOne[i];
          removePointsFromParticipant(par, points);
          list1.add(
              new OlympiadInfo(
                  par.getName(),
                  par.getClanName(),
                  par.getClanId(),
                  par.getBaseClass(),
                  _damageT1,
                  par.getStats().getInt(POINTS) - points,
                  -points));
        }

        points = min / MAX_TEAM_SIZE;
        for (int i = 0; i < _teamTwoSize; i++) {
          par = _teamTwo[i];
          par.updateStat(COMP_WON, 1);
          addPointsToParticipant(par, points);
          list2.add(
              new OlympiadInfo(
                  par.getName(),
                  par.getClanName(),
                  par.getClanId(),
                  par.getBaseClass(),
                  _damageT2,
                  par.getStats().getInt(POINTS) + points,
                  points));
        }

        winside = 2;

        for (int i = 0; i < _teamTwoSize; i++) {
          rewardParticipant(_teamTwo[i].getPlayer(), getReward());
        }
      } else {
        stadium.broadcastPacket(
            SystemMessage.getSystemMessage(
                SystemMessageId.THERE_IS_NO_VICTOR_THE_MATCH_ENDS_IN_A_TIE));

        for (int i = 0; i < _teamOneSize; i++) {
          par = _teamOne[i];
          par.updateStat(COMP_DRAWN, 1);
          points =
              Math.min(par.getStats().getInt(POINTS) / getDivider(), Config.ALT_OLY_MAX_POINTS);
          removePointsFromParticipant(par, points);
          list1.add(
              new OlympiadInfo(
                  par.getName(),
                  par.getClanName(),
                  par.getClanId(),
                  par.getBaseClass(),
                  _damageT1,
                  par.getStats().getInt(POINTS) - points,
                  -points));
        }

        for (int i = 0; i < _teamTwoSize; i++) {
          par = _teamTwo[i];
          par.updateStat(COMP_DRAWN, 1);
          points =
              Math.min(par.getStats().getInt(POINTS) / getDivider(), Config.ALT_OLY_MAX_POINTS);
          removePointsFromParticipant(par, points);
          list2.add(
              new OlympiadInfo(
                  par.getName(),
                  par.getClanName(),
                  par.getClanId(),
                  par.getBaseClass(),
                  _damageT2,
                  par.getStats().getInt(POINTS) - points,
                  -points));
        }
        tie = true;
      }

      for (int i = _teamOneSize; --i >= 0; ) {
        par = _teamOne[i];
        par.updateStat(COMP_DONE, 1);
        par.updateStat(COMP_DONE_WEEK, 1);
        par.updateStat(getWeeklyMatchType(), 1);
      }

      for (int i = _teamTwoSize; --i >= 0; ) {
        par = _teamTwo[i];
        par.updateStat(COMP_DONE, 1);
        par.updateStat(COMP_DONE_WEEK, 1);
        par.updateStat(getWeeklyMatchType(), 1);
      }
      if (winside == 1) {
        result = new ExOlympiadMatchResult(tie, winside, list1, list2);
      } else {
        result = new ExOlympiadMatchResult(tie, winside, list2, list1);
      }
      stadium.broadcastPacket(result);
    } catch (Exception e) {
      _log.log(Level.WARNING, "Exception on validateWinner(): " + e.getMessage(), e);
    }
  }