diff --git a/hypixel-api-core/src/main/java/net/hypixel/api/data/type/GuildAchievement.java b/hypixel-api-core/src/main/java/net/hypixel/api/data/type/GuildAchievement.java new file mode 100644 index 00000000..cd8b0466 --- /dev/null +++ b/hypixel-api-core/src/main/java/net/hypixel/api/data/type/GuildAchievement.java @@ -0,0 +1,32 @@ +package net.hypixel.api.data.type; + +/** + * Types of achievements that can be earned by guilds on Hypixel. + *

+ * Created using slothpixel/hypixelconstants + * as a reference. + */ +public enum GuildAchievement { + /** + * A tiered achievement based on the highest amount of experience earned by a guild in a single + * day. + */ + EXPERIENCE_KINGS, + + /** + * A tiered achievement based on the highest number of members a guild has had online at the + * same time. + */ + ONLINE_PLAYERS, + + /** + * A tiered achievement based on a guild's highest level. + */ + PRESTIGE, + + /** + * A tiered achievement based on the highest number of combined wins (in mini-games) between + * members of a guild on the same day. + */ + WINNERS +} diff --git a/hypixel-api-core/src/main/java/net/hypixel/api/reply/GuildReply.java b/hypixel-api-core/src/main/java/net/hypixel/api/reply/GuildReply.java index 862079f4..e23cfbc4 100644 --- a/hypixel-api-core/src/main/java/net/hypixel/api/reply/GuildReply.java +++ b/hypixel-api-core/src/main/java/net/hypixel/api/reply/GuildReply.java @@ -1,12 +1,23 @@ package net.hypixel.api.reply; -import net.hypixel.api.util.Banner; - +import com.google.gson.annotations.SerializedName; +import java.time.LocalDate; import java.time.ZonedDateTime; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.UUID; +import net.hypixel.api.data.type.GameType; +import net.hypixel.api.data.type.GuildAchievement; +import net.hypixel.api.reply.PlayerReply.Player; +import net.hypixel.api.util.Banner; +// Suppressed because most fields are assigned by Gson via reflection. +@SuppressWarnings({"unused", "RedundantSuppression", "MismatchedQueryAndUpdateOfCollection"}) public class GuildReply extends AbstractReply { + private Guild guild; public Guild getGuild() { @@ -16,127 +27,525 @@ public Guild getGuild() { @Override public String toString() { return "GuildReply{" + - "guild=" + guild + - "} " + super.toString(); + "guild=" + guild + + "} " + super.toString(); } public static class Guild { - private String _id; + // Unclear/unconventionally named fields. + @SerializedName("_id") + private String id; + @SerializedName("created") + private ZonedDateTime creationDate; + @SerializedName("exp") + private long experience; + @SerializedName("publiclyListed") + private boolean isPubliclyListed; + @SerializedName("joinable") + private boolean isJoinable; + + // If any of these variables change names, make sure to include a @SerializedName("..."). private String name; private String description; private String tag; private String tagColor; - private Boolean publiclyListed; private Banner banner; private List members; + private List ranks; + private List preferredGames; + private Map guildExpByGameType; + private Map achievements; private int coins; private int coinsEver; - private ZonedDateTime created; - private Boolean joinable; - private long exp; - private int legacyRanking; + private Integer legacyRanking; // Nullable so that non-ranked guilds don't appear as #1. + /** + * The unique BSON ObjectId that represents the guild. This should not change during the + * guild's lifetime. + * + * @return the guild's main identifier. + * @see ObjectId + */ + public String getId() { + return id; + } + + /** + * @deprecated Renamed to {@link #getId()}. + */ + @Deprecated public String get_id() { - return _id; + return getId(); } + /** + * The guild's main display name. This is subject to change at any time. + * + * @return the guild's display name. + */ public String getName() { return name; } + /** + * A short, optional string set by a privileged member of the guild, and displayed in the + * in-game guild finder. + * + * @return the guild's description, or {@code null} if none has been set. + */ public String getDescription() { return description; } + /** + * The date when the guild was created. If the guild has been disbanded and recreated in the + * past, this is the date when the guild was most recently created. + * + * @return the date when the guild was created. + */ + public ZonedDateTime getCreationDate() { + return creationDate; + } + + /** + * @deprecated Renamed to {@link #getCreationDate()}. + */ + @Deprecated + public ZonedDateTime getCreated() { + return getCreationDate(); + } + + /** + * A short string displayed in-game after the names of members of the guild. + * + * @return the guild's tag, or {@code null} if the guild does not have one (or if it has not + * been set). + */ public String getTag() { return tag; } + /** + * A Minecraft color code indicating the color of the guild's {@link #getTag() tag}. If this + * returns {@code null} but the guild does have a tag, then the color is assumed to be + * "{@code GRAY}" (without quotes). + * + * @return the name of a Minecraft color code (all uppercase), or {@code null} if the guild + * has never changed its tag's color. + * @see Color codes + * table (uses lowercase names) + */ public String getTagColor() { return tagColor; } - public Boolean getPubliclyListed() { - return publiclyListed; - } - + /** + * The Minecraft-style banner displayed on the guild's hypixel.net website profile. + * + * @return the guild's banner, or {@code null} if none has been set. + */ public Banner getBanner() { return banner; } + /** + * Information about the Hypixel players who are currently members of the guild (at the time + * the {@code Guild} object was fetched from the API). + * + * @return an immutable list of all of the guild's members. + */ public List getMembers() { - return members; + return members == null + ? Collections.emptyList() + : Collections.unmodifiableList(members); } - public int getCoins() { - return coins; + /** + * A list of permission groups created within the guild. + * + * @return an immutable list of the guild's ranks. May be empty. + * @apiNote This list may not be exhaustive, and typically only includes user-generated + * ranks. Built-in ranks, and pre-guild-update ranks may not be included in this list, + * despite being valid values for a member's {@link Member#getRank() rank} field. Extraneous + * rank names include: + *

+ */ + public List getRanks() { + return ranks == null + ? Collections.emptyList() + : Collections.unmodifiableList(ranks); } - public int getCoinsEver() { - return coinsEver; + /** + * A list of games that can be used to search for the guild via the in-game guild finder. + * Typically, this list represents the games that the guild considers their main focus. + * + * @return an immutable list of the guild's preferred games. May be empty. + */ + public List getPreferredGames() { + return preferredGames == null + ? Collections.emptyList() + : Collections.unmodifiableList(preferredGames); } - public ZonedDateTime getCreated() { - return created; + /** + * Retrieves the total amount of {@link #getExperience() experience} that the guild has + * earned from a particular game. + * + * @param game The game to retrieve experience for. + * @return the amount of XP earned by the guild for the specified {@code game}. + * @throws IllegalArgumentException if the provided {@code game} is {@code null}. + */ + public int getExperienceForGame(GameType game) { + if (game == null) { + throw new IllegalArgumentException("Cannot get XP for null GameType"); + } + + return Optional.ofNullable(guildExpByGameType) + .map(expByGame -> expByGame.get(game)) + .orElse(0); } - public Boolean getJoinable() { - return joinable; + /** + * Retrieves the guild's high-score for a specific guild achievement. The meaning of "score" + * varies between achievements, and can be found in the documentation for the desired {@link + * GuildAchievement}. + * + * @param achievement the achievement to get the high-score of. + * @return the guild's high-score for the provided achievement. + */ + public int getAchievementHighScore(GuildAchievement achievement) { + if (achievement == null) { + throw new IllegalArgumentException("Cannot get high-score for null achievement"); + } + return Optional.ofNullable(achievements) + .map(highScores -> highScores.get(achievement)) + .orElse(0); + } + + /** + * The total amount of experience earned by the guild's members. This is different from a + * player's {@link Player#getNetworkExp() network experience}, which is independent of the + * guild system. + * + * @return the guild's total experience count. + */ + public long getExperience() { + return experience; } + /** + * @deprecated Renamed to {@link #getExperience()}. + */ + @Deprecated public long getExp() { - return exp; + return getExperience(); + } + + /** + * Whether or not the guild can be discovered via the in-game guild finder. + * + * @return whether or not the guild is listed publicly. + */ + public boolean isPubliclyListed() { + return isPubliclyListed; + } + + /** + * @deprecated Renamed to {@link #isPubliclyListed()}. + */ + @Deprecated + public Boolean getPubliclyListed() { + return isPubliclyListed(); + } + + /** + * Whether or not players can request to join the guild. If {@code false}, players must be + * invited by a guild member with appropriate privileges. + * + * @return whether or not the guild can be joined without an invite. + */ + public boolean isJoinable() { + return isJoinable; + } + + /** + * @deprecated Renamed to {@link #isJoinable()}. + */ + @Deprecated + public Boolean getJoinable() { + return isJoinable(); + } + + /** + * The number of coins that the guild had prior to the 2018 guild update (when they were + * replaced with {@link #getExperience() guild experience}). Coins were previously used to + * purchase cosmetics for guilds (member slots, tags, etc), but now are only stored for + * legacy purposes. + * + * @return the number of coins the guild has. + */ + public int getCoins() { + return coins; + } + + /** + * The total number of coins earned by the guild prior to the 2018 guild update. Unlike + * {@link #getCoins()}, this number did not decrease when the guild purchased cosmetics + * using coins. + * + * @return the number of coins earned during the guild's lifetime. + * @see #getCoins() + */ + public int getCoinsEver() { + return coinsEver; } + /** + * The guild's ranking, out of all guilds, in terms of {@link #getCoins() coins} earned + * before the 2018 guild update. The lowest place is {@code 1} (meaning 1st place) for + * guilds that this applies to. For guilds created after the update, {@code -1} is + * returned. + * + * @return the guild's position on the legacy coin leaderboard, or {@code -1} if the guild + * was created after the guild update. + * @see #getCoins() + * @see #getCoinsEver() + */ public int getLegacyRanking() { - return legacyRanking; + return Optional.ofNullable(legacyRanking) + .map(ranking -> ranking + 1) + .orElse(-1); } @Override public String toString() { return "Guild{" + - "_id='" + _id + '\'' + - ", name='" + name + '\'' + - ", description='" + description + '\'' + - ", tag='" + tag + '\'' + - ", tagColor='" + tagColor + '\'' + - ", publiclyListed=" + publiclyListed + - ", banner=" + banner + - ", members=" + members + - ", coins=" + coins + - ", coinsEver=" + coinsEver + - ", created=" + created + - ", joinable=" + joinable + - ", exp=" + exp + - ", legacyRanking=" + legacyRanking + - '}'; + "id='" + id + '\'' + + ", name='" + name + '\'' + + ", description='" + description + '\'' + + ", creationDate=" + creationDate + + ", tag='" + tag + '\'' + + ", tagColor='" + tagColor + '\'' + + ", banner=" + banner + + ", members=" + members + + ", ranks=" + ranks + + ", experience=" + experience + + ", isPubliclyListed=" + isPubliclyListed + + ", isJoinable=" + isJoinable + + ", coins=" + coins + + ", coinsEver=" + coinsEver + + ", legacyRanking=" + legacyRanking + + '}'; } + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Guild guild = (Guild) o; + return Objects.equals(id, guild.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + /** + * Information about a Hypixel player pertaining to their guild. + */ public static class Member { + private UUID uuid; private String rank; - private ZonedDateTime joined; + @SerializedName("joined") + private ZonedDateTime joinDate; + @SerializedName("expHistory") + private Map weeklyExperience; + /** + * The player's Minecraft identifier (version 4 UUID), assigned by Mojang. + * + * @return the player's UUID. + */ public UUID getUuid() { return uuid; } + /** + * The player's permission group in the guild. This rank name may not appear in the + * guild's rank list; see {@link Guild#getRanks() here} for details. + * + * @return the player's guild rank. + */ public String getRank() { return rank; } + /** + * The date and time when the player joined the guild. If they have joined and left the + * guild previously, this will be the date when they most recently re-joined. + * + * @return the date when the player joined their guild. + */ + public ZonedDateTime getJoinDate() { + return joinDate; + } + + /** + * Retrieves the amount of guild experience earned by the player on a particular date. + * Daily XP information is typically only kept for one week, so results may not be found + * for earlier dates. + * + * @param date The date to get the member's experience earnings for. + * @return the amount of guild experience earned by the player on the {@code date}, or + * {@code -1} if no total is kept for that day. + */ + public int getExperienceEarned(LocalDate date) { + if (date == null) { + throw new IllegalArgumentException("Cannot get XP for null date"); + } + + return Optional.ofNullable(weeklyExperience) + .map(expByDate -> expByDate.get(date.toString())) + .orElse(-1); + } + + /** + * @deprecated Renamed to {@link #getJoinDate()}. + */ + @Deprecated public ZonedDateTime getJoined() { - return joined; + return getJoinDate(); } @Override public String toString() { return "Member{" + - "uuid=" + uuid + - ", rank=" + rank + - ", joined=" + joined + - '}'; + "uuid=" + uuid + + ", rank='" + rank + '\'' + + ", joined=" + joinDate + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Member member = (Member) o; + return Objects.equals(uuid, member.uuid); + } + + @Override + public int hashCode() { + return Objects.hash(uuid); + } + } + + /** + * A permission group that can be assigned to members of a Hypixel guild. + */ + public static class Rank { + + private String name; + private String tag; + private int priority; + @SerializedName("default") + private boolean isDefault; + @SerializedName("created") + private ZonedDateTime creationDate; + + /** + * The rank's display name, as seen in guild chat and hypixel.net. + * + * @return the rank's name. + */ + public String getName() { + return name; + } + + /** + * A short string prefixed before the guild-chat messages of members with the rank. + * + * @return the rank's guild-chat prefix. + */ + public String getChatTag() { + return tag; + } + + /** + * Whether or not the rank is given to members initially upon joining the guild. + * + * @return a boolean indicating if the rank is the guild's default or not. If no rank in + * the guild's list is marked with this, the default is the legacy "{@code MEMBER}" rank + * (without quotes). + */ + public boolean isDefault() { + return isDefault; + } + + /** + * The date and time when the rank was added to to the guild. + * + * @return the rank's creation time. + */ + public ZonedDateTime getCreationDate() { + return creationDate; + } + + /** + * The rank's order in the guild's rank hierarchy. Members with appropriate permissions + * cannot modify those of a rank with a higher priority than their own. + * + * @return the rank's permission priority. + * @apiNote Higher Priority = Higher Privilege (and vice-versa) + */ + public int getPriority() { + return priority; + } + + @Override + public String toString() { + return "Rank{" + + "name='" + name + '\'' + + ", tag='" + tag + '\'' + + ", isDefault=" + isDefault + + ", creationDate=" + creationDate + + ", priority=" + priority + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Rank rank = (Rank) o; + return Objects.equals(name, rank.name) && + Objects.equals(creationDate, rank.creationDate); + } + + @Override + public int hashCode() { + return Objects.hash(name, creationDate); } } } diff --git a/hypixel-api-core/src/main/java/net/hypixel/api/util/Banner.java b/hypixel-api-core/src/main/java/net/hypixel/api/util/Banner.java index e1cd9e4e..11b2cbae 100644 --- a/hypixel-api-core/src/main/java/net/hypixel/api/util/Banner.java +++ b/hypixel-api-core/src/main/java/net/hypixel/api/util/Banner.java @@ -1,42 +1,142 @@ package net.hypixel.api.util; import com.google.gson.annotations.SerializedName; - +import java.util.Collections; import java.util.List; +import java.util.Objects; +/** + * A Minecraft-style banner design. + *


+ * + * Color Code Reference + *

    + *
  • {@code 0}: Black
  • + *
  • {@code 1}: Red
  • + *
  • {@code 2}: Green
  • + *
  • {@code 3}: Brown
  • + *
  • {@code 4}: Blue
  • + *
  • {@code 5}: Purple
  • + *
  • {@code 6}: Cyan
  • + *
  • {@code 7}: Silver (Light Grey)
  • + *
  • {@code 8}: Grey (Dark Grey)
  • + *
  • {@code 9}: Pink
  • + *
  • {@code 10}: Lime
  • + *
  • {@code 11}: Yellow
  • + *
  • {@code 12}: Light Blue
  • + *
  • {@code 13}: Magenta
  • + *
  • {@code 14}: Orange
  • + *
  • {@code 15}: White
  • + *
+ * These numeric color codes are returned by the following methods: + *
    + *
  • {@link #getBase()}
  • + *
  • {@link Pattern#getColor()}
  • + *
+ * + * @see Banner (Minecraft Wiki) + */ public class Banner { @SerializedName("Base") - private String base; + private String baseColor; @SerializedName("Patterns") private List patterns; + /** + * An integer (wrapped in a string) indicating the background/base color of the banner. See the + * linked cheat-sheet for a list of possible values. + * + * @return the banner's background color. + * @see Color code cheat-sheet + */ + public String getBaseColor() { + return baseColor; + } + + /** + * @deprecated Renamed to {@link #getBaseColor()}. + */ + @Deprecated public String getBase() { - return base; + return getBaseColor(); } + /** + * The shapes that compose the banner, minus the {@link #getBaseColor() base/background layer}. + * Patterns in the list are ordered from background to foreground, meaning that the last pattern + * in the list will always be displayed on top. + * + * @return an immutable list of the banner's layers. + */ public List getPatterns() { - return patterns; + return patterns == null + ? Collections.emptyList() + : Collections.unmodifiableList(patterns); } @Override public String toString() { return "Banner{" + - "base='" + base + '\'' + - ", patterns=" + patterns + - '}'; + "baseColor='" + baseColor + '\'' + + ", patterns=" + patterns + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Banner banner = (Banner) o; + return Objects.equals(baseColor, banner.baseColor) && + Objects.equals(patterns, banner.patterns); + } + + @Override + public int hashCode() { + return Objects.hash(baseColor, patterns); } + /** + * A colored shape that makes up a layer of a {@link Banner} design. + */ public static class Pattern { + @SerializedName("Pattern") - private String pattern; + private String type; @SerializedName("Color") private String color; + /** + * A short identifier indicating the shape to be used for the layer. See the link below for + * each type's identifier. + * + * @return the pattern's type identifier. + * @see Pattern identifiers + */ + public String getType() { + return type; + } + + /** + * @deprecated Renamed to {@link #getType()}. + */ + @Deprecated public String getPattern() { - return pattern; + return getType(); } + /** + * An integer (wrapped in a string) indicating the color used to draw the pattern's shape. + * See the linked cheat-sheet for a list of possible values. + * + * @return the pattern's color. + * @see Banner Color code cheat-sheet + */ public String getColor() { return color; } @@ -44,9 +144,27 @@ public String getColor() { @Override public String toString() { return "Pattern{" + - "pattern='" + pattern + '\'' + - ", color='" + color + '\'' + - '}'; + "type='" + type + '\'' + + ", color='" + color + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Pattern pattern = (Pattern) o; + return Objects.equals(type, pattern.type) && + Objects.equals(color, pattern.color); + } + + @Override + public int hashCode() { + return Objects.hash(type, color); } } } diff --git a/hypixel-api-example/src/main/java/net/hypixel/api/example/ExampleUtil.java b/hypixel-api-example/src/main/java/net/hypixel/api/example/ExampleUtil.java index 94190af6..38c15f18 100644 --- a/hypixel-api-example/src/main/java/net/hypixel/api/example/ExampleUtil.java +++ b/hypixel-api-example/src/main/java/net/hypixel/api/example/ExampleUtil.java @@ -17,6 +17,7 @@ public class ExampleUtil { } public static final UUID HYPIXEL = UUID.fromString("f7c77d99-9f15-4a66-a87d-c4a51ef30d19"); + public static final String GUILD_ID = "53bd67d7ed503e868873eceb"; /** * Keep the program alive till we explicitly exit. diff --git a/hypixel-api-example/src/main/java/net/hypixel/api/example/GetGuildExample.java b/hypixel-api-example/src/main/java/net/hypixel/api/example/GetGuildExample.java index 91997b7c..45f96ff7 100644 --- a/hypixel-api-example/src/main/java/net/hypixel/api/example/GetGuildExample.java +++ b/hypixel-api-example/src/main/java/net/hypixel/api/example/GetGuildExample.java @@ -1,8 +1,263 @@ package net.hypixel.api.example; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.ExecutionException; +import net.hypixel.api.HypixelAPI; +import net.hypixel.api.data.type.GameType; +import net.hypixel.api.data.type.GuildAchievement; +import net.hypixel.api.reply.GuildReply; +import net.hypixel.api.reply.GuildReply.Guild; +import net.hypixel.api.reply.GuildReply.Guild.Member; +import net.hypixel.api.reply.GuildReply.Guild.Rank; +import net.hypixel.api.util.IGuildLeveling; + +/** + * A sample app for demonstrating how guilds can be fetched & used from the Hypixel API. + */ public class GetGuildExample { + public static void main(String[] args) { - ExampleUtil.API.getGuildByPlayer(ExampleUtil.HYPIXEL).whenComplete(ExampleUtil.getTestConsumer()); - ExampleUtil.await(); + /* + * Make sure you have a HypixelAPI object set up. You can see how this is done by going to + * the ExampleUtil class. + * + * See the finally{} block below for how to shutdown this API once you're all done. + */ + HypixelAPI api = ExampleUtil.API; + + /* + * Skip below the try/catch/finally block to see how this is used. + */ + GuildReply apiReply; + + try { + /* + * We'll be fetching the guild's stats using its ID for this example, but guilds can + * also be looked up using their name, or one of their members' Minecraft UUIDs. + * - HypixelAPI.getGuildByName(String) + * - HypixelAPI.getGuildByPlayer(UUID) + */ + String guildId = ExampleUtil.GUILD_ID; + + /* + * Here, we store the response from the API in our variable. + * + * We call `.get()` at the end so that we can use the reply in the same thread. + * The downside is that the current thread freezes (or "blocks") until the API responds. + * If this is a problem for you, instead use: + * + * .whenComplete((apiReply, error) -> { + * // Do something with apiReply (in a different thread)... + * }); + * + * But for a simple command-line app like this one, `.get()` will do the job. + */ + apiReply = api.getGuildById(guildId).get(); + + } catch (ExecutionException e) { + System.err.println("Oh no, our API request failed!"); + + /* + * If an ExecutionException is thrown, it's typically because of an API error. + * Use `getCause()` to determine what the actual problem is. + */ + e.getCause().printStackTrace(); + return; + + } catch (InterruptedException e) { + // Shouldn't happen under normal circumstances. + System.err.println("Oh no, the guild fetch thread was interrupted!"); + e.printStackTrace(); + Thread.currentThread().interrupt(); + return; + + } finally { + /* + * Once you're finished with all your requests, you can shutdown your HypixelAPI object. + * + * If your app is meant to run continuously, you probably don't want to do this until + * the app is stopped/closed. For this example though, we only need the one request. + */ + api.shutdown(); + } + + /* + * Now that we have the guild, we can start to read its information and stats! + */ + Guild guild = apiReply.getGuild(); + + // =================================================== + // Check out the methods referenced below to see how + // each type of stat is retrieved! (their code can be + // found further down in this file) + // =================================================== + + /* + * First we'll display some basic information about the guild, like its name, tag, + * description, and level. + */ + printGuildSummary(guild); + System.out.println(); + + /* + * After that, we'll print the guild's high-score for each tiered guild achievement. + */ + printAchievementScores(guild); + System.out.println(); + + /* + * Then we'll display how much experience the guild has earned from each game on Hypixel, + * as well as an overall total. + */ + printGuildXpPerGame(guild); + System.out.println(); + + /* + * Next, we'll print some info about each of the guild's ranks, if it has any. + */ + List ranks = guild.getRanks(); + if (!ranks.isEmpty()) { + printGuildRanks(ranks); + System.out.println(); + } + + /* + * Finally, we'll print some information about each member in the guild. + * + * This might print out A LOT, so you may want to comment the following line out if you're + * focusing on some of the guild's other info. + */ + printGuildMembers(guild.getMembers()); + } + + private static void printGuildSummary(Guild guild) { + /* + * First, we'll print the guild's name. If it also has a tag, we'll print that on the same + * line. + */ + System.out.print(guild.getName()); + if (guild.getTag() != null) { + System.out.print(" [" + guild.getTag() + "]"); + } + System.out.println(); + + int guildLevel = (int) IGuildLeveling.getLevel(guild.getExperience()); + + System.out.println("\tID: " + guild.getId()); + System.out.println("\tLevel: " + guildLevel); + System.out.println("\tCreated At: " + guild.getCreationDate()); + System.out.println("\tDescription: \"" + guild.getDescription() + '"'); + System.out.println("\tGames: " + guild.getPreferredGames()); + System.out.println("\tBanner: " + guild.getBanner()); + } + + private static void printAchievementScores(Guild guild) { + System.out.println("Guild Achievement High-Scores"); + + /* + * Displays the guild's high-score for each tiered achievement. The meaning of "score" + * varies between achievements, but an explanation for each can be found in the + * `GuildAchievement` class. + */ + for (GuildAchievement achievement : GuildAchievement.values()) { + int highScore = guild.getAchievementHighScore(achievement); + System.out.println("\t" + achievement + ": " + highScore); + } + } + + private static void printGuildXpPerGame(Guild guild) { + System.out.println("Guild XP Breakdown"); + + /* + * This line prints the guild's total experience from all games. + */ + System.out.println("\tOVERALL: " + guild.getExperience()); + + /* + * Then we loop through each game and see how much experience the guild's earned from it. + */ + for (GameType game : GameType.values()) { + int experienceForGame = guild.getExperienceForGame(game); + System.out.println("\t" + game.getName() + ": " + experienceForGame); + } + } + + private static void printGuildRanks(List ranks) { + System.out.println("Ranks (" + ranks.size() + " total)"); + + /* + * This just sorts the list in reverse order by priority, so that higher-level ranks (like + * officer) are printed before lower-level ones (like member). + * + * The first line copies the list beforehand, because `Guild.getRanks()` returns an + * immutable (unmodifiable) list that can't be altered (including sorting). + */ + ranks = new ArrayList<>(ranks); + ranks.sort(Comparator.comparingInt(Rank::getPriority).reversed()); + + for (Rank rank : ranks) { + /* + * Here we print the rank's name. If it also has a chat tag, we print that on the + * same line. + */ + System.out.print("\t" + rank.getName()); + if (rank.getChatTag() != null) { + System.out.print(" [" + rank.getChatTag() + "]"); + } + System.out.println(); + + System.out.println("\t\tPriority: " + rank.getPriority()); + System.out.println("\t\tCreated at " + rank.getCreationDate()); + } + } + + private static void printGuildMembers(List members) { + System.out.println("Members (" + members.size() + " total)"); + + for (Member member : members) { + /* + * First we'll print some basic information about each member. + * + * Notice how we only have the member's UUID. If you want to get their name, you'll have + * to make a separate request to the API using this UUID. See the GetPlayerExample class + * for an example of that. + */ + System.out.println("\tUUID: " + member.getUuid()); + System.out.println("\tRank: " + member.getRank()); + System.out.println("\tJoin date: " + member.getJoinDate()); + + /* + * Then, we'll print how much guild experience they earned for the last 7 days. We'll + * sum up these daily totals to print an overall (weekly) total at the end. + * + * The code for the `getWeekDates()` function can be found at the bottom of the class. + */ + int weeklyExp = 0; + System.out.println("\tWeekly Exp: "); + for (LocalDate date : getWeekDates()) { + int dailyExp = member.getExperienceEarned(date); + weeklyExp += dailyExp; + + // ": " + System.out.println("\t\t" + date + ": " + dailyExp); + } + System.out.println("\t\tWeekly Total: " + weeklyExp); + System.out.println(); + } + } + + /* + * Returns an array containing the date for each of the past 7 days (including today). + * We use this to get each member's weekly experience by day (see `main` method above). + */ + private static LocalDate[] getWeekDates() { + LocalDate[] week = new LocalDate[7]; + for (int i = 0; i < 7; i++) { + week[i] = LocalDate.now().minusDays(i); + } + return week; } }