gt:         if (challenge != null && completion != null) {
context: package us.talabrek.ultimateskyblock.challenge;
  
  import org.bukkit.*;
  import org.bukkit.block.Block;
  import org.bukkit.configuration.file.FileConfiguration;
  import org.bukkit.entity.Entity;
  import org.bukkit.entity.EntityType;
  import org.bukkit.entity.Player;
  import org.bukkit.inventory.Inventory;
  import org.bukkit.inventory.ItemStack;
  import org.bukkit.inventory.PlayerInventory;
  import org.bukkit.inventory.meta.ItemMeta;
  import us.talabrek.ultimateskyblock.SkyBlockMenu;
  import us.talabrek.ultimateskyblock.player.PlayerInfo;
  import us.talabrek.ultimateskyblock.handler.VaultHandler;
  import us.talabrek.ultimateskyblock.uSkyBlock;
  
  import java.util.*;
  import java.util.logging.Level;
  import java.util.regex.Pattern;
  
  import static us.talabrek.ultimateskyblock.util.I18nUtil.tr;
  
  /**
   * The home of challenge business logic.
   */
  public class ChallengeLogic {
      private static final Pattern ITEM_AMOUNT_PATTERN = Pattern.compile("(?<id>[0-9]+)(:(?<data>[0-9]+))?:(?<amount>[0-9]+)");
      public static final int MS_MIN = 60*1000;
      public static final int MS_HOUR = 60*MS_MIN;
      public static final long MS_DAY = 24*MS_HOUR;
      public static final int ROWS_OF_RANKS = 6;
  
      private final FileConfiguration config;
      private final uSkyBlock skyBlock;
      private final Map<String, Rank> ranks;
  
      public final ChallengeDefaults defaults;
  
      public ChallengeLogic(FileConfiguration config, uSkyBlock skyBlock) {
          this.config = config;
          this.skyBlock = skyBlock;
          this.defaults = ChallengeFactory.createDefaults(config.getRoot());
          load();
          ranks = ChallengeFactory.createRankMap(config.getConfigurationSection("ranks"), defaults);
      }
  
      public boolean isEnabled() {
          return config.getBoolean("allowChallenges", true);
      }
      private void load() {
          Arrays.asList(config.getString("ranks", "").split(" "));
      }
  
      public List<Rank> getRanks() {
          return Collections.unmodifiableList(new ArrayList<>(ranks.values()));
      }
  
      public List<String> getAvailableChallengeNames(PlayerInfo playerInfo) {
          List<String> list = new ArrayList<>();
          for (Rank rank : ranks.values()) {
              if (rank.isAvailable(playerInfo)) {
                  for (Challenge challenge : rank.getChallenges()) {
                      list.add(challenge.getName());
                  }
              } else {
                  break;
              }
          }
          return list;
      }
  
      public List<String> getAllChallengeNames() {
          List<String> list = new ArrayList<>();
          for (Rank rank : ranks.values()) {
              for (Challenge challenge : rank.getChallenges()) {
                  list.add(challenge.getName());
              }
          }
          return list;
      }
  
      public List<Challenge> getChallengesForRank(String rank) {
          return ranks.get(rank).getChallenges();
      }
  
      public boolean completeChallenge(final Player player, final String challengeName) {
          final PlayerInfo pi = skyBlock.getPlayerInfo(player);
          Challenge challenge = getChallenge(challengeName);
          ChallengeCompletion completion = pi.getChallenge(challengeName);
          if (!challenge.getRank().isAvailable(pi) || !pi.challengeExists(challengeName) || completion.getTimesCompleted() > 0 && (!challenge.isRepeatable() || challenge.getType() == Challenge.Type.ISLAND)) {
              player.sendMessage(tr("\u00a74The {0} challenge is not repeatable!", challengeName));
              return false;
          }
          if (challenge.getType() == Challenge.Type.PLAYER) {
              if (!tryComplete(player, challengeName, "onPlayer")) {
                  player.sendMessage(tr("\u00a74{0}", challenge.getDescription()));
                  player.sendMessage(tr("\u00a74You don't have enough of the required item(s)!"));
                  return false;
              }
              return true;
          } else if (challenge.getType() == Challenge.Type.ISLAND) {
              if (!skyBlock.playerIsOnIsland(player)) {
                  player.sendMessage(tr("\u00a74You must be on your island to do that!"));
                  return false;
              }
              if (!tryComplete(player, challengeName, "onIsland")) {
                  player.sendMessage(tr("\u00a74{0}", challenge.getDescription()));
                  player.sendMessage(tr("\u00a74You must be standing within {0} blocks of all required items.", challenge.getRadius()));
                  return false;
              }
              return true;
          } else if (challenge.getType() == Challenge.Type.ISLAND_LEVEL) {
              if (!tryCompleteIslandLevel(player, challenge)) {
                  player.sendMessage(tr("\u00a74Your island must be level {0} to complete this challenge!", challenge.getRequiredLevel()));
              }
              return true;
          }
          return false;
      }
  
      public Challenge getChallenge(String challengeName) {
          for (Rank rank : ranks.values()) {
              for (Challenge challenge : rank.getChallenges()) {
                  if (challenge.getName().equalsIgnoreCase(challengeName)) {
                      return challenge;
                  }
              }
          }
          return null;
      }
  
      public static int calcAmount(int amount, char op, int inc, int timesCompleted) {
          switch (op) {
              case '+':
                  return amount + inc * timesCompleted;
              case '-':
                  return amount - inc * timesCompleted; // Why?
              case '*':
                  return amount * inc * timesCompleted; // Oh, my god! Just do the time m8!
              case '/':
                  return amount / (inc * timesCompleted); // Yay! Free stuff!!!
          }
          return amount;
      }
  
      public boolean tryComplete(final Player player, final String challenge, final String type) {
          if (type.equalsIgnoreCase("onPlayer")) {
              return tryCompleteOnPlayer(player, challenge);
          } else if (type.equalsIgnoreCase("onIsland")) {
              return tryCompleteOnIsland(player, challenge);
          } else {
              player.sendMessage(tr("\u00a74Unknown type of challenge: {0}", type));
          }
          return true;
      }
  
      private boolean tryCompleteIslandLevel(Player player, Challenge challenge) {
          if (skyBlock.getIslandInfo(player).getLevel() >= challenge.getRequiredLevel()) {
              giveReward(player, challenge.getName());
              return true;
          }
          return false;
      }
  
      private boolean islandContains(Player player, List<ItemStack> itemStacks, int radius) {
          final Location l = player.getLocation();
          final int px = l.getBlockX();
          final int py = l.getBlockY();
          final int pz = l.getBlockZ();
          World world = l.getWorld();
          int[] blockCount = new int[0xffffff];
          int[] baseBlocks = new int[0xffff];
          for (int x = px - radius; x <= px + radius; x++) {
              for (int y = py - radius; y <= py + radius; y++) {
                  for (int z = pz - radius; z <= pz + radius; z++) {
                      Block block = world.getBlockAt(x, y, z);
                      blockCount[(block.getTypeId() << 8) + (block.getData() & 0xff)]++;
                      baseBlocks[block.getTypeId()]++;
                  }
              }
          }
          StringBuilder sb = new StringBuilder();
          boolean hasAll = true;
          for (ItemStack item : itemStacks) {
              int diffSpecific = item.getAmount() - blockCount[(item.getTypeId() << 8) + (item.getDurability() & 0xff)];
              int diffGeneral = item.getAmount() - baseBlocks[item.getTypeId()];
              if (item.getDurability() != 0 && diffSpecific > 0) {
                  sb.append(" \u00a74" + diffSpecific
                          + " \u00a7b" + VaultHandler.getItemName(item));
                  hasAll = false;
              } if (diffGeneral > 0) {
                  sb.append(" \u00a74" + diffGeneral
                          + " \u00a7b" + VaultHandler.getItemName(item));
                  hasAll = false;
              }
          }
          if (!hasAll) {
              player.sendMessage(tr("\u00a7eStill the following blocks short: {0}", sb.toString()));
          }
          return hasAll;
      }
  
      private boolean tryCompleteOnIsland(Player player, String challengeName) {
          Challenge challenge = getChallenge(challengeName);
          List<ItemStack> requiredItems = challenge.getRequiredItems(0);
          int radius = challenge.getRadius();
          if (islandContains(player, requiredItems, radius) && hasEntitiesNear(player, challenge.getRequiredEntities(), radius)) {
              giveReward(player, challengeName);
              return true;
          }
          return false;
      }
  
      private boolean hasEntitiesNear(Player player, List<EntityMatch> requiredEntities, int radius) {
          Map<EntityMatch, Integer> countMap = new LinkedHashMap<>();
          Map<EntityType, Set<EntityMatch>> matchMap = new HashMap<>();
          for (EntityMatch match : requiredEntities) {
              countMap.put(match, match.getCount());
              Set<EntityMatch> set = matchMap.get(match.getType());
              if (set == null) {
                  set = new HashSet<>();
              }
              set.add(match);
              matchMap.put(match.getType(), set);
          }
          List<Entity> nearbyEntities = player.getNearbyEntities(radius, radius, radius);
          for (Entity entity : nearbyEntities) {
              if (matchMap.containsKey(entity.getType())) {
                  for (Iterator<EntityMatch> it = matchMap.get(entity.getType()).iterator(); it.hasNext();) {
                      EntityMatch match = it.next();
                      if (match.matches(entity)) {
                          int newCount = countMap.get(match) - 1;
                          if (newCount <= 0) {
                              countMap.remove(match);
                              it.remove();
                          } else {
                              countMap.put(match, newCount);
                          }
                      }
                  }
              }
          }
          if (!countMap.isEmpty()) {
              StringBuilder sb = new StringBuilder();
              for (Map.Entry<EntityMatch,Integer> entry : countMap.entrySet()) {
                  sb.append("\u00a7e - ");
                  sb.append(" \u00a74" + entry.getValue() + " \u00a7ex");
                  sb.append(" \u00a7b" + entry.getKey() + "\n");
              }
              player.sendMessage(tr("\u00a7eStill the following entities short:\n{0}", sb.toString()).split("\n"));
          }
          return countMap.isEmpty();
      }
  
      private boolean tryCompleteOnPlayer(Player player, String challengeName) {
          Challenge challenge = getChallenge(challengeName);
          PlayerInfo playerInfo = skyBlock.getPlayerInfo(player);
          ChallengeCompletion completion = playerInfo.getChallenge(challengeName);
  