Merge pull request #10 in MIN/mineplex from leaderboards_dev to master

* commit 'e1f7e2dbcc91bb79d393b09ea5b250fe895cfe11':
  Remove old lines of debug code.
  Add in hooks to update statistical events log for leaderboards. Modify leaderboard PHP script for new updated leaderboard table formats.
This commit is contained in:
Jonathan Williams 2015-02-21 01:55:59 -06:00
commit 87558eb01a
8 changed files with 304 additions and 87 deletions

View File

@ -0,0 +1,80 @@
package mineplex.core.leaderboard;
import mineplex.core.MiniPlugin;
import mineplex.core.account.CoreClient;
import mineplex.core.account.CoreClientManager;
import mineplex.core.spawn.command.SpawnCommand;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
/**
* Manages dynamic Leaderboard statistics.
*
* Used for recording stat events, retrieving customized leaderboards, etc.
* @author MrTwiggy
*
*/
public class LeaderboardManager extends MiniPlugin
{
private static LeaderboardManager _instance; // Singleton instance of Leaderboard Manager
private StatEventsRepository _statEvents; // 'statEvents' table repository.
private CoreClientManager _clientManager;
private String _serverGroup;
/**
* Private class constructor to prevent non-singleton instances.
*/
public LeaderboardManager(JavaPlugin plugin, CoreClientManager clientManager)
{
super("Leaderboard Manager", plugin);
_instance = this;
_clientManager = clientManager;
_statEvents = new StatEventsRepository(plugin);
_serverGroup = _plugin.getConfig().getString("serverstatus.group");
}
/**
* Attempt to trigger a stat event.
* @param player - the player responsible for the statistic
* @param stat - the display name of the statistic to be added
* @param value - the counter value used to increment the statistic
* @return true, if a stat event was successfully triggered and logged, false otherwise.
*/
public boolean attemptStatEvent(Player player, String stat, int gamemode, int value)
{
StatType type = StatType.getType(stat);
return (type == null) ? false : onStatEvent(player, type, gamemode, value);
}
/**
* Trigger a stat event to be recorded.
* @param player - the player responsible for the statistic
* @param type - the unique type id designating the statistic being recorded
* @param gamemode - the unique gamemode id associated with the stat event
* @param value - the counter value used to increment the statistic
* @return true, if the stat event was successfully triggered and logged, false otherwise.
*/
public boolean onStatEvent(Player player, StatType type, int gamemode, int value)
{
_statEvents.insertStatEvent(player.getName(), gamemode, _serverGroup, type.getTypeId(), value);
return true;
}
@Override
public void AddCommands()
{
addCommand(new SetTournamentCommand(this));
}
/**
* @return the singleton instance for {@link LeaderboardManager}.
*/
public static LeaderboardManager getInstance()
{
return _instance;
}
}

View File

@ -0,0 +1,27 @@
package mineplex.core.leaderboard;
import mineplex.core.command.CommandBase;
import mineplex.core.common.Rank;
import org.bukkit.entity.Player;
public class SetTournamentCommand extends CommandBase<LeaderboardManager>
{
public SetTournamentCommand(LeaderboardManager plugin)
{
super(plugin, Rank.ADMIN, "settournament", "set-tournament");
}
@Override
public void Execute(Player caller, String[] args)
{
// TODO: Implement set tournament command.
/*if (args.length == 3)
{
String statType = args[0];
int gamemode = Integer.parseInt(args[1]);
int value = Integer.parseInt(args[2]);
LeaderboardManager.getInstance().attemptStatEvent(caller, statType, gamemode, value);
}*/
}
}

View File

@ -0,0 +1,69 @@
package mineplex.core.leaderboard;
import mineplex.core.database.RepositoryBase;
import mineplex.core.database.column.ColumnInt;
import mineplex.core.database.column.ColumnVarChar;
import org.bukkit.plugin.java.JavaPlugin;
/**
* StatEventsRepository offers the ability to insert and log newly generated stat events.
*
* Intended for the purpose of statistical tracking of players.
* @author MrTwiggy
*
*/
public class StatEventsRepository extends RepositoryBase
{
// Insert or update stat events query
/*private static String INSERT_EVENT =
"INSERT INTO statEvents(accountId, gamemode, serverGroup, type, value, date) "
+ "VALUES (?, ?, ?, ?, ?, CURRENT_DATE()) "
+ "ON DUPLICATE KEY UPDATE value=value+";*/
private static String INSERT_EVENT =
"INSERT INTO statEvents(accountId, gamemode, serverGroup, type, value, date) "
+ "SELECT accounts.id, ?, ?, ?, ?, CURRENT_DATE() "
+ "FROM accounts WHERE name = ? "
+ "ON DUPLICATE KEY UPDATE value=value+";
/**
* Class constructor
* @param plugin - the plugin responsible for instantiating this repository.
*/
public StatEventsRepository(JavaPlugin plugin)
{
super(plugin, "jdbc:mysql://db.mineplex.com:3306/Account?autoReconnect=true&failOverReadOnly=false&maxReconnects=10", "root", "tAbechAk3wR7tuTh");
}
@Override
protected void initialize()
{
//executeUpdate(CREATE_EVENTS_TABLE);
//executeUpdate(CREATE_STAT_RELATION_TABLE);
}
@Override
protected void update()
{
}
/**
* Insert (or update) a new stat event record for today into the repository.
* @param accountId - the id of the account responsible for the stat event.
* @param gamemode - the id of the gamemode type at the time of the stat event.
* @param serverGroup - the server group id associated with the stat event.
* @param type - the type of stat event to be inserted (id of type).
* @param value - the integer based value denoting the actual statistic being logged.
*/
public void insertStatEvent(String playerName, int gamemode, String serverGroup, int type, int value)
{
// Hacky string concatanation - Don't judge me!!
// TODO: How to handle outside value block parameters
executeUpdate(INSERT_EVENT + value + ";", new ColumnInt("gamemode", gamemode), new ColumnVarChar("serverGroup", 100, serverGroup),
new ColumnInt("type", type), new ColumnInt("value", value), new ColumnVarChar("name", 100, playerName));
}
}

View File

@ -0,0 +1,48 @@
package mineplex.core.leaderboard;
/**
* An enumeration delegating the various types of statistics to be dynamically tracked.
* @author MrTwiggy
*
*/
public enum StatType
{
WIN(1),
LOSS(2),
KILL(3),
DEATH(4);
private int _typeId; // Unique id for stat type
public int getTypeId() { return _typeId; }
/**
* Private class constructor
* @param typeId - the unique identifying id for this {@link StatType}
*/
private StatType(int typeId)
{
_typeId = typeId;
}
/**
* @param stat - the display name for the stat type
* @return the {@link StatType} corresponding to the passed in {@code stat}, if one exists,
* null otherwise.
*/
public static StatType getType(String stat)
{
switch(stat.toUpperCase().trim())
{
case "WINS":
return WIN;
case "LOSSES":
return LOSS;
case "KILLS":
return KILL;
case "DEATHS":
return DEATH;
default:
return null;
}
}
}

View File

@ -25,6 +25,7 @@ import mineplex.core.hologram.HologramManager;
import mineplex.core.ignore.IgnoreManager;
import mineplex.core.inventory.InventoryManager;
import mineplex.core.itemstack.ItemStackFactory;
import mineplex.core.leaderboard.LeaderboardManager;
import mineplex.core.memory.MemoryFix;
import mineplex.core.message.MessageManager;
import mineplex.core.monitor.LagMeter;
@ -92,6 +93,7 @@ public class Arcade extends JavaPlugin
Creature creature = new Creature(this);
ServerStatusManager serverStatusManager = new ServerStatusManager(this, _clientManager, new LagMeter(this, _clientManager));
LeaderboardManager leaderboardManager = new LeaderboardManager(this, _clientManager);
new Spawn(this, serverStatusManager.getCurrentServerName());
Teleport teleport = new Teleport(this);
Portal portal = new Portal(this, _clientManager, serverStatusManager.getCurrentServerName());

View File

@ -5,78 +5,78 @@ import org.bukkit.Material;
public enum GameType
{
//Mini
BaconBrawl("Bacon Brawl", Material.PORK, (byte)0, GameCategory.ARCADE),
Barbarians("A Barbarians Life", Material.WOOD_AXE, (byte)0, GameCategory.ARCADE),
Bridge("The Bridges", Material.IRON_PICKAXE, (byte)0, GameCategory.SURVIVAL),
CastleSiege("Castle Siege", Material.DIAMOND_CHESTPLATE, (byte)0, GameCategory.CLASSICS),
ChampionsTDM("Champions TDM", "Champions", Material.GOLD_SWORD, (byte)0, GameCategory.CHAMPIONS),
ChampionsDominate("Champions Domination", "Champions", Material.BEACON, (byte)0, GameCategory.CHAMPIONS),
ChampionsMOBA("Champions MOBA", "Champions", Material.SKULL_ITEM, (byte)0, GameCategory.CHAMPIONS),
Christmas("Christmas Chaos", Material.SNOW_BALL, (byte)0, GameCategory.CLASSICS),
DeathTag("Death Tag", Material.SKULL_ITEM, (byte)0, GameCategory.ARCADE),
DragonEscape("Dragon Escape", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE),
DragonEscapeTeams("Dragon Escape Teams", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE),
DragonRiders("Dragon Riders", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE),
Dragons("Dragons", Material.ENDER_STONE, (byte)0, GameCategory.ARCADE),
DragonsTeams("Dragons Teams", Material.ENDER_STONE, (byte)0, GameCategory.ARCADE),
Draw("Draw My Thing", Material.BOOK_AND_QUILL, (byte)0, GameCategory.CLASSICS),
Evolution("Evolution", Material.EMERALD, (byte)0, GameCategory.ARCADE),
FlappyBird("Flappy Bird", Material.FEATHER, (byte)0, GameCategory.ARCADE),
Gravity("Gravity", Material.ENDER_PORTAL, (byte)0, GameCategory.ARCADE),
Halloween("Halloween Horror", Material.PUMPKIN, (byte)0, GameCategory.CLASSICS),
HideSeek("Block Hunt", Material.GRASS, (byte)0, GameCategory.CLASSICS),
Horse("Horseback", Material.IRON_BARDING, (byte)0, GameCategory.ARCADE),
SurvivalGames("Survival Games", Material.IRON_SWORD, (byte)0, GameCategory.SURVIVAL),
SurvivalGamesTeams("Survival Games Teams", Material.IRON_SWORD, (byte)0, GameCategory.SURVIVAL),
Micro("Micro Battle", Material.LAVA_BUCKET, (byte)0, GameCategory.ARCADE),
MineStrike("MineStrike", Material.TNT, (byte)0, GameCategory.CLASSICS),
MineWare("MineWare", Material.PAPER, (byte)0, GameCategory.ARCADE),
MilkCow("Milk the Cow", Material.MILK_BUCKET, (byte)0, GameCategory.ARCADE),
Paintball("Super Paintball", Material.ENDER_PEARL, (byte)0, GameCategory.ARCADE),
Quiver("One in the Quiver", Material.ARROW, (byte)0, GameCategory.ARCADE),
QuiverTeams("One in the Quiver Teams", Material.ARROW, (byte)0, GameCategory.ARCADE),
Runner("Runner", Material.LEATHER_BOOTS, (byte)0, GameCategory.ARCADE),
SearchAndDestroy("Search and Destroy", Material.TNT, (byte)0, GameCategory.SURVIVAL),
Sheep("Sheep Quest", Material.WOOL, (byte)4, GameCategory.ARCADE),
Smash("Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS),
SmashTeams("Super Smash Mobs Teams", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS),
SmashDomination("Super Smash Mobs Domination", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS),
Snake("Snake", Material.WOOL, (byte)0, GameCategory.ARCADE),
SneakyAssassins("Sneaky Assassins", Material.INK_SACK, (byte)0, GameCategory.ARCADE),
SnowFight("Snow Fight", Material.SNOW_BALL, (byte)0, GameCategory.ARCADE),
Spleef("Super Spleef", Material.IRON_SPADE, (byte)0, GameCategory.ARCADE),
SpleefTeams("Super Spleef Teams", Material.IRON_SPADE, (byte)0, GameCategory.ARCADE),
Stacker("Super Stacker", Material.BOWL, (byte)0, GameCategory.ARCADE),
SquidShooter("Squid Shooter", Material.FIREWORK_CHARGE, (byte)0, GameCategory.ARCADE),
Tug("Tug of Wool", Material.WHEAT, (byte)0, GameCategory.ARCADE),
TurfWars("Turf Wars", Material.STAINED_CLAY, (byte)14, GameCategory.ARCADE),
UHC("Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.SURVIVAL),
WitherAssault("Wither Assault", Material.SKULL_ITEM, (byte)1, GameCategory.ARCADE),
Wizards("Wizards", Material.BLAZE_ROD, (byte)0, GameCategory.SURVIVAL),
ZombieSurvival("Zombie Survival", Material.SKULL_ITEM, (byte)2, GameCategory.SURVIVAL);
BaconBrawl("Bacon Brawl", Material.PORK, (byte)0, GameCategory.ARCADE, 1),
Barbarians("A Barbarians Life", Material.WOOD_AXE, (byte)0, GameCategory.ARCADE, 2),
Bridge("The Bridges", Material.IRON_PICKAXE, (byte)0, GameCategory.SURVIVAL, 3),
CastleSiege("Castle Siege", Material.DIAMOND_CHESTPLATE, (byte)0, GameCategory.CLASSICS, 4),
ChampionsTDM("Champions TDM", "Champions", Material.GOLD_SWORD, (byte)0, GameCategory.CHAMPIONS, 5),
ChampionsDominate("Champions Domination", "Champions", Material.BEACON, (byte)0, GameCategory.CHAMPIONS, 6),
ChampionsMOBA("Champions MOBA", "Champions", Material.SKULL_ITEM, (byte)0, GameCategory.CHAMPIONS, 7),
Christmas("Christmas Chaos", Material.SNOW_BALL, (byte)0, GameCategory.CLASSICS, 8),
DeathTag("Death Tag", Material.SKULL_ITEM, (byte)0, GameCategory.ARCADE, 9),
DragonEscape("Dragon Escape", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE, 10),
DragonEscapeTeams("Dragon Escape Teams", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE, 11),
DragonRiders("Dragon Riders", Material.DRAGON_EGG, (byte)0, GameCategory.ARCADE, 12),
Dragons("Dragons", Material.ENDER_STONE, (byte)0, GameCategory.ARCADE, 13),
DragonsTeams("Dragons Teams", Material.ENDER_STONE, (byte)0, GameCategory.ARCADE, 14),
Draw("Draw My Thing", Material.BOOK_AND_QUILL, (byte)0, GameCategory.CLASSICS, 15),
Evolution("Evolution", Material.EMERALD, (byte)0, GameCategory.ARCADE, 16),
FlappyBird("Flappy Bird", Material.FEATHER, (byte)0, GameCategory.ARCADE, 17),
Gravity("Gravity", Material.ENDER_PORTAL, (byte)0, GameCategory.ARCADE, 18),
Halloween("Halloween Horror", Material.PUMPKIN, (byte)0, GameCategory.CLASSICS, 19),
HideSeek("Block Hunt", Material.GRASS, (byte)0, GameCategory.CLASSICS, 20),
Horse("Horseback", Material.IRON_BARDING, (byte)0, GameCategory.ARCADE, 21),
SurvivalGames("Survival Games", Material.IRON_SWORD, (byte)0, GameCategory.SURVIVAL, 22),
SurvivalGamesTeams("Survival Games Teams", Material.IRON_SWORD, (byte)0, GameCategory.SURVIVAL, 23),
Micro("Micro Battle", Material.LAVA_BUCKET, (byte)0, GameCategory.ARCADE, 24),
MineStrike("MineStrike", Material.TNT, (byte)0, GameCategory.CLASSICS, 25),
MineWare("MineWare", Material.PAPER, (byte)0, GameCategory.ARCADE, 26),
MilkCow("Milk the Cow", Material.MILK_BUCKET, (byte)0, GameCategory.ARCADE, 27),
Paintball("Super Paintball", Material.ENDER_PEARL, (byte)0, GameCategory.ARCADE, 28),
Quiver("One in the Quiver", Material.ARROW, (byte)0, GameCategory.ARCADE, 29),
QuiverTeams("One in the Quiver Teams", Material.ARROW, (byte)0, GameCategory.ARCADE, 30),
Runner("Runner", Material.LEATHER_BOOTS, (byte)0, GameCategory.ARCADE, 31),
SearchAndDestroy("Search and Destroy", Material.TNT, (byte)0, GameCategory.SURVIVAL, 32),
Sheep("Sheep Quest", Material.WOOL, (byte)4, GameCategory.ARCADE, 33),
Smash("Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS, 34),
SmashTeams("Super Smash Mobs Teams", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS, 35),
SmashDomination("Super Smash Mobs Domination", "Super Smash Mobs", Material.SKULL_ITEM, (byte)4, GameCategory.CLASSICS, 36),
Snake("Snake", Material.WOOL, (byte)0, GameCategory.ARCADE, 37),
SneakyAssassins("Sneaky Assassins", Material.INK_SACK, (byte)0, GameCategory.ARCADE, 38),
SnowFight("Snow Fight", Material.SNOW_BALL, (byte)0, GameCategory.ARCADE, 39),
Spleef("Super Spleef", Material.IRON_SPADE, (byte)0, GameCategory.ARCADE, 40),
SpleefTeams("Super Spleef Teams", Material.IRON_SPADE, (byte)0, GameCategory.ARCADE, 41),
Stacker("Super Stacker", Material.BOWL, (byte)0, GameCategory.ARCADE, 42),
SquidShooter("Squid Shooter", Material.FIREWORK_CHARGE, (byte)0, GameCategory.ARCADE, 43),
Tug("Tug of Wool", Material.WHEAT, (byte)0, GameCategory.ARCADE, 44),
TurfWars("Turf Wars", Material.STAINED_CLAY, (byte)14, GameCategory.ARCADE, 45),
UHC("Ultra Hardcore", Material.GOLDEN_APPLE, (byte)0, GameCategory.SURVIVAL, 46),
WitherAssault("Wither Assault", Material.SKULL_ITEM, (byte)1, GameCategory.ARCADE, 47),
Wizards("Wizards", Material.BLAZE_ROD, (byte)0, GameCategory.SURVIVAL, 48),
ZombieSurvival("Zombie Survival", Material.SKULL_ITEM, (byte)2, GameCategory.SURVIVAL, 49);
String _name;
String _lobbyName;
Material _mat;
byte _data;
GameCategory _gameCategory;
private int _gameId; // Unique identifying id for this gamemode (used for statistics)
public int getGameId() { return _gameId; }
GameType(String name, Material mat, byte data, GameCategory gameCategory)
GameType(String name, Material mat, byte data, GameCategory gameCategory, int gameId)
{
_name = name;
_lobbyName = name;
_mat = mat;
_data = data;
_gameCategory = gameCategory;
this(name, name, mat, data, gameCategory, gameId);
}
GameType(String name, String lobbyName, Material mat, byte data, GameCategory gameCategory)
GameType(String name, String lobbyName, Material mat, byte data, GameCategory gameCategory, int gameId)
{
_name = name;
_lobbyName = lobbyName;
_mat = mat;
_data = data;
_gameCategory = gameCategory;
_gameId = gameId;
}
public String GetName()

View File

@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.UUID;
import mineplex.core.common.util.C;
import mineplex.core.leaderboard.LeaderboardManager;
import nautilus.game.arcade.ArcadeManager;
import nautilus.game.arcade.events.GameStateChangeEvent;
import nautilus.game.arcade.game.Game.GameState;
@ -60,7 +61,13 @@ public class GameStatManager implements Listener
{
for (String stat : event.GetGame().GetStats().get(player).keySet())
{
Manager.GetStatsManager().incrementStat(player, stat, event.GetGame().GetStats().get(player).get(stat));
int value = event.GetGame().GetStats().get(player).get(stat);
Manager.GetStatsManager().incrementStat(player, stat, value);
// Leaderboard hook for logging appropriate stat events
// Note: Rejects stat events that are not of the appropriate types.
int gameId = event.GetGame().GetType().getGameId();
LeaderboardManager.getInstance().attemptStatEvent(player, stat.split("\\.")[1], gameId, value);
}
}
}

View File

@ -27,8 +27,8 @@
<div class="jumbotron" style="text-align: center">
<div class="container" style="text-align: center">
<img src="mineplex.png" alt="Mineplex"/>
<h1>The Fall Invitational</h1>
<h2>Tournament Leaderboard</h2>
<h1>The Tournament</h1>
<h2>Leaderboard</h2>
</div>
</div>
@ -39,9 +39,10 @@
<?php
$tournamentTypes = array('Super Smash Mobs', 'Survival Games', 'Mixed Arcade');
$tournamentTypes = array('Tournament');
$con = mysqli_connect('db.mineplex.com', 'root', 'tAbechAk3wR7tuTh', 'Account');
//$con = mysqli_connect('localhost', 'root', 'ZXquwQyEdKMB', 'Development');
for ($i = 0; $i < count($tournamentTypes); $i++)
{
@ -60,49 +61,32 @@ for ($i = 0; $i < count($tournamentTypes); $i++)
<th class="center">Rank</th>
<th>Player</th>
<th class="center">Wins</th>
<th class="center">Losses</th>
<th class="center">Score*</th>
</tr>
<?php
$query = <<<QUERY
SELECT name, wins, total, score
FROM tournamentLeaderboard
JOIN accounts ON accounts.id = accountId
WHERE tournamentId = 0
AND gameId = $i
AND score IS NOT NULL
ORDER BY score DESC, name ASC
$query = <<<QUERY
SELECT LB.rank, accounts.name, LB.value AS 'wins'
FROM TournamentLB LB
INNER JOIN accounts ON accounts.id = accountId
ORDER BY rank ASC
LIMIT 30;
QUERY;
$result = mysqli_query($con, $query);
$index = 1;
$rank = 1;
$lastScore = null;
while($row = mysqli_fetch_array($result))
{
$score = $row['score'];
if ($score != $lastScore)
{
$rank = $index;
}
while($row = mysqli_fetch_array($result))
{
?>
<tr>
<td class="center"><?php echo $rank ?></td>
<td class="center"><?php echo $row['rank'] ?></td>
<td><?php echo $row['name'] ?></td>
<td class="center"><?php echo $row['wins'] ?></td>
<td class="center"><?php echo ($row['total'] - $row['wins']) ?></td>
<td class="center"><?php echo round($score*100, 3) ?></td>
</tr>
<?php
$index++;
$lastScore = $score;
}
?>