Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api implementation #4

Merged
merged 3 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>BedWars1058-GroupStats</artifactId>
<groupId>me.infinity.groupstats</groupId>
<version>9.0-SNAPSHOT</version>
<version>9.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
10 changes: 10 additions & 0 deletions api/src/main/java/me/infinity/groupstats/api/GroupStatsAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package me.infinity.groupstats.api;

import java.util.Map;
import java.util.UUID;

public interface GroupStatsAPI {

Map<String, GroupNode> getPlayerStatisticsMap(UUID uuid, boolean cache);

}
2 changes: 1 addition & 1 deletion build/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>BedWars1058-GroupStats</artifactId>
<groupId>me.infinity.groupstats</groupId>
<version>9.0-SNAPSHOT</version>
<version>9.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
7 changes: 6 additions & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<artifactId>BedWars1058-GroupStats</artifactId>
<groupId>me.infinity.groupstats</groupId>
<version>9.0-SNAPSHOT</version>
<version>9.1-SNAPSHOT</version>
</parent>

<artifactId>core</artifactId>
Expand Down Expand Up @@ -141,5 +141,10 @@
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sparkjava</groupId>
<artifactId>spark-core</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
</project>
32 changes: 32 additions & 0 deletions core/src/main/java/me/infinity/groupstats/core/API.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package me.infinity.groupstats.core;

import me.infinity.groupstats.api.GroupNode;
import me.infinity.groupstats.api.GroupStatsAPI;
import org.bukkit.plugin.ServicePriority;

import java.util.Map;
import java.util.Optional;
import java.util.UUID;

public class API implements GroupStatsAPI {

private final GroupStatsPlugin instance;

public API(GroupStatsPlugin instance) {
this.instance = instance;
this.instance.getServer().getServicesManager().register(GroupStatsAPI.class, this, instance, ServicePriority.Normal);
}

@Override
public Map<String, GroupNode> getPlayerStatisticsMap(UUID uuid, boolean cache) {
Map<String, GroupNode> result;
if (cache) {
Optional<GroupProfile> groupProfileOptional = Optional.ofNullable(instance.getGroupManager().getGroupProfileCache().get(uuid));
result = groupProfileOptional.map(GroupProfile::getGroupStatistics).orElse(null);
} else {
Optional<GroupProfile> groupProfileOptional = Optional.ofNullable(instance.getGroupManager().fetchUnsafe(uuid));
result = groupProfileOptional.map(GroupProfile::getGroupStatistics).orElse(null);
}
return result;
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package me.infinity.groupstats.core;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.ConcurrentHashMap;
import lombok.RequiredArgsConstructor;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import me.infinity.groupstats.api.GroupNode;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.concurrent.ConcurrentHashMap;

@RequiredArgsConstructor
public class GroupStatsExpansion extends PlaceholderExpansion {

Expand Down Expand Up @@ -204,26 +205,31 @@ public double getRatio(GroupNode groupNode, String type) {
deaths = 1;
}
result = this.getRatio(groupNode.getKills(), deaths);
break;
case "fkdr":
int finalDeaths = groupNode.getFinalDeaths();
if (finalDeaths == 0) {
finalDeaths = 1;
}
result = this.getRatio(groupNode.getFinalKills(), finalDeaths);
break;
case "bblr":
int bedsLost = groupNode.getBedsLost();
if (bedsLost == 0) {
bedsLost = 1;
}
result = this.getRatio(groupNode.getBedsBroken(), bedsLost);
break;
case "wlr":
int losses = groupNode.getLosses();
if (losses == 0) {
losses = 1;
}
result = this.getRatio(groupNode.getWins(), losses);
break;
default:
result = Double.NaN;
break;
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import com.google.gson.reflect.TypeToken;
import lombok.Getter;
import me.infinity.groupstats.api.GroupNode;
import me.infinity.groupstats.api.GroupStatsAPI;
import me.infinity.groupstats.core.manager.DatabaseManager;
import me.infinity.groupstats.core.manager.GroupManager;
import me.infinity.groupstats.core.manager.RequestsManager;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SimplePie;
import org.bukkit.command.CommandExecutor;
Expand All @@ -32,6 +34,10 @@ public final class GroupStatsPlugin extends JavaPlugin implements CommandExecuto

private DatabaseManager databaseManager;
private GroupManager groupManager;
private GroupStatsExpansion groupStatsExpansion;
private RequestsManager requestsManager;

private GroupStatsAPI groupStatsAPI;

@Override
public void onEnable() {
Expand All @@ -55,12 +61,18 @@ public void onEnable() {

this.databaseManager = new DatabaseManager(this);
this.groupManager = new GroupManager(this);
new GroupStatsExpansion(this).register();

this.groupStatsExpansion = new GroupStatsExpansion(this);
this.groupStatsExpansion.register();

this.requestsManager = new RequestsManager(this);

Metrics metrics = new Metrics(this, 16815);
metrics.addCustomChart(new SimplePie("bedwars_plugin_type", () -> "bedwars1058"));
metrics.addCustomChart(new SimplePie("database_type", () -> databaseManager.isDbEnabled() ? "MySQL" : "SQLite"));

this.groupStatsAPI = new API(this);

this.getLogger().info("Loaded the plugin successfully.");
this.startupCompleted = true;
}
Expand All @@ -72,6 +84,9 @@ public void onDisable() {
if (isBw1058()) this.groupManager.saveAll();
this.databaseManager.closeDatabase();
}
if (requestsManager != null) {
requestsManager.onDisable();
}
this.getLogger().info("Plugin disabled successfully.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.andrei1058.bedwars.api.events.player.PlayerBedBreakEvent;
import com.andrei1058.bedwars.api.events.player.PlayerKillEvent;
import com.andrei1058.bedwars.api.events.player.PlayerLeaveArenaEvent;
import java.util.UUID;
import lombok.SneakyThrows;
import me.infinity.groupstats.api.GroupNode;
import me.infinity.groupstats.core.GroupProfile;
Expand All @@ -19,6 +18,8 @@
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

import java.util.UUID;

public class GroupStatsListener implements Listener {

private final GroupStatsPlugin instance;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package me.infinity.groupstats.core.manager;

import me.infinity.groupstats.api.GroupNode;
import me.infinity.groupstats.core.GroupProfile;
import me.infinity.groupstats.core.GroupStatsPlugin;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.scheduler.BukkitRunnable;
import org.json.simple.JSONObject;
import spark.Spark;

import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class RequestsManager {

private final GroupStatsPlugin instance;
private boolean apiActive;

public RequestsManager(GroupStatsPlugin instance) {
this.instance = instance;
this.apiActive = this.instance.getConfig().getBoolean("api.enabled", false);
if (apiActive) {
enableApi();
}
}

private void enableApi() {
new BukkitRunnable() {
@Override
public void run() {
if (!apiActive) {
return;
}
int port = instance.getConfig().getInt("api.port");
if (port == 0) {
apiActive = false;
return;
}
instance.getLogger().info("Detected that Rest API is enabled. Enabling Rest API now.");
Spark.port(port);
instance.getLogger().info("Set GroupStats API to listen on port " + port);
Spark.get("/stats", (req, res) -> {
res.type("application/json");
Set<String> params = req.queryParams();
OfflinePlayer offlinePlayer;
if (params.contains("uuid")) {
try {
UUID uuid = UUID.fromString(req.queryParams("uuid"));
offlinePlayer = Bukkit.getOfflinePlayer(uuid);
} catch (IllegalArgumentException ex) {
return getFailJson("Invalid UUID provided");
}
} else if (params.contains("name")) {
String username = req.queryParams("name");
//noinspection deprecation
offlinePlayer = Bukkit.getOfflinePlayer(username);
} else {
res.status(411);
return getFailJson("Invalid name provided");
}

JSONObject json = getPlayerStats(offlinePlayer);
if (json == null) {
return getFailJson("Player data is empty");
}
res.status(201);
return json.toString();
});
}
}.runTaskAsynchronously(instance);
}

public void onDisable() {
if (!apiActive) {
return;
}
Spark.stop();
}

@SuppressWarnings("unchecked")
private JSONObject getFailJson(String reason) {
JSONObject json = new JSONObject();
json.put("status", "Failed");
json.put("reason", reason);

return json;
}

@SuppressWarnings("unchecked")
private JSONObject getPlayerStats(OfflinePlayer offlinePlayer) {
GroupProfile profile = this.instance.getGroupManager().fetchUnsafe(offlinePlayer.getUniqueId());
if (profile == null) {
return null;
}

JSONObject json = new JSONObject();
json.put("status", "Success");
json.put("name", offlinePlayer.getName());

ConcurrentHashMap<String, GroupNode> stats = GroupStatsPlugin.GSON.fromJson(profile.getData(),
GroupStatsPlugin.STATISTIC_MAP_TYPE);

JSONObject statsObject = new JSONObject();

//<editor-fold desc="Overall stats">
JSONObject overallStats = new JSONObject();
overallStats.put("games played", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getGamesPlayed).sum());
overallStats.put("beds broken", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getBedsBroken).sum());
overallStats.put("beds lost", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getBedsLost).sum());
overallStats.put("kills", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getKills).sum());
overallStats.put("deaths", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getDeaths).sum());
overallStats.put("final kills", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getFinalKills).sum());
overallStats.put("final deaths", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getFinalDeaths).sum());
overallStats.put("wins", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getWins).sum());
overallStats.put("losses", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getLosses).sum());
overallStats.put("winstreak", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getWinstreak).sum());
overallStats.put("highest winstreak", stats.isEmpty() ? 0
: stats.values().stream().mapToInt(GroupNode::getHighestWinstreak).sum());
overallStats.put("kdr", instance.getGroupStatsExpansion().getRatio(
stats.isEmpty() ? 0 : stats.values().stream().mapToInt(GroupNode::getKills).sum(),
stats.isEmpty() ? 0 : stats.values().stream().mapToInt(GroupNode::getDeaths).sum()));
overallStats.put("fkdr", instance.getGroupStatsExpansion().getRatio(
stats.isEmpty() ? 0 : stats.values().stream().mapToInt(GroupNode::getFinalKills).sum(),
stats.isEmpty() ? 0 : stats.values().stream().mapToInt(GroupNode::getFinalDeaths).sum()));
overallStats.put("bblr", instance.getGroupStatsExpansion().getRatio(
stats.isEmpty() ? 0 : stats.values().stream().mapToInt(GroupNode::getBedsBroken).sum(),
stats.isEmpty() ? 0 : stats.values().stream().mapToInt(GroupNode::getBedsLost).sum()));
overallStats.put("wlr", instance.getGroupStatsExpansion().getRatio(
stats.isEmpty() ? 0 : stats.values().stream().mapToInt(GroupNode::getWins).sum(),
stats.isEmpty() ? 0 : stats.values().stream().mapToInt(GroupNode::getLosses).sum()));
statsObject.put("over-all", overallStats);
//</editor-fold>


//<editor-fold desc="Per group stats">
stats.forEach((name, node) -> {
JSONObject groupJson = new JSONObject();

groupJson.put("games played", node.getGamesPlayed());
groupJson.put("beds broken", node.getBedsBroken());
groupJson.put("beds lost", node.getBedsLost());
groupJson.put("kills", node.getKills());
groupJson.put("deaths", node.getDeaths());
groupJson.put("final kills", node.getFinalKills());
groupJson.put("final deaths", node.getFinalDeaths());
groupJson.put("wins", node.getWins());
groupJson.put("losses", node.getLosses());
groupJson.put("winstreak", node.getWinstreak());
groupJson.put("highest winstreak", node.getHighestWinstreak());
groupJson.put("kdr", instance.getGroupStatsExpansion().getRatio(node, "kdr"));
groupJson.put("fkdr", instance.getGroupStatsExpansion().getRatio(node, "fkdr"));
groupJson.put("bblr", instance.getGroupStatsExpansion().getRatio(node, "bblr"));
groupJson.put("wlr", instance.getGroupStatsExpansion().getRatio(node, "wlr"));

statsObject.put(name, groupJson);
});
//</editor-fold>

json.put("stats", statsObject);

return json;
}

}
10 changes: 8 additions & 2 deletions core/src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,11 @@ database-credentials:
password: "pass"
useSSL: false

# IGNORE IF YOU ARE RUNNING THIS PLUGIN ON A BW PROXY INSTANCE
update-timer: 1 # At how much minute delay should the plugin save player data.
# IGNORE IF YOU ARE RUNNING THIS PLUGIN ON A BW PROXY INSTANCE
update-timer: 1 # At how much minute delay should the plugin save player data.

# Should we enable REST API for group stats, please view our wiki for more information
# DO NOT CHANGE THIS IF YOU DO NOT KNOW WHAT YOU ARE DOING
api:
enabled: false
port: 8080
Loading
Loading