If only git knew to add new files...

This commit is contained in:
garbagemule 2012-03-08 00:00:35 +01:00
parent 48acd00d47
commit a036891996
7 changed files with 547 additions and 0 deletions

View File

@ -0,0 +1,63 @@
package com.garbagemule.MobArena.log;
import java.util.HashMap;
import java.util.Map;
import com.garbagemule.MobArena.ArenaPlayer;
import com.garbagemule.MobArena.framework.Arena;
import com.garbagemule.MobArena.util.MutableInt;
public class ArenaLog
{
private Arena arena;
private LogSessionBuilder sessionBuilder;
private LogTotalsBuilder totalsBuilder;
public ArenaLog(Arena arena, LogSessionBuilder sessionBuilder, LogTotalsBuilder totalsBuilder) {
this.arena = arena;
this.sessionBuilder = sessionBuilder;
this.totalsBuilder = totalsBuilder;
}
public void start() {
// Log number of players.
sessionBuilder.buildNumberOfPlayers(arena.getPlayersInArena().size());
// Log the distribution of classes.
Map<String,MutableInt> classDistribution = new HashMap<String,MutableInt>();
for (String classname : arena.getClasses().keySet()) {
classDistribution.put(classname, new MutableInt());
}
for (ArenaPlayer ap : arena.getArenaPlayerSet()) {
classDistribution.get(ap.getArenaClass().getName()).inc();
}
sessionBuilder.buildClassDistribution(classDistribution);
totalsBuilder.updateClassDistribution(classDistribution);
// Log the current time and set it as the start time.
sessionBuilder.buildStartTime();
totalsBuilder.recordStartTime();
}
public void end() {
// Log the end time and duration
sessionBuilder.buildEndTime();
sessionBuilder.buildDuration();
totalsBuilder.updateTimePlayed();
totalsBuilder.updateSessionsPlayed();
// Update the last wave.
totalsBuilder.updateLastWave(arena.getWaveManager().getWaveNumber());
// Finalize the session.
sessionBuilder.finalize();
totalsBuilder.finish();
}
public void playerLeave(ArenaPlayer ap) {
ArenaLogPlayerEntry entry = ArenaLogPlayerEntry.create(ap);
sessionBuilder.buildPlayerEntry(entry, arena.getRewardManager().getRewards(ap.getPlayer()));
totalsBuilder.updatePlayerEntry(entry);
}
}

View File

@ -0,0 +1,53 @@
package com.garbagemule.MobArena.log;
import java.util.Date;
import java.util.Map;
import org.bukkit.Material;
import com.garbagemule.MobArena.ArenaPlayer;
import com.garbagemule.MobArena.ArenaPlayerStatistics;
public class ArenaLogPlayerEntry
{
/**
* Player name is used as a unique ID.
*/
protected String playername, classname;
/**
* All recordable statistics.
*/
protected int kills, dmgDone, dmgTaken, swings, hits, lastWave;
/**
* The time at which the player left or died.
*/
protected long leaveTime;
/**
* Total amounts of each item rewarded.
*/
protected Map<Material,Integer> rewards;
private ArenaLogPlayerEntry() {}
public static ArenaLogPlayerEntry create(ArenaPlayer ap) {
ArenaLogPlayerEntry entry = new ArenaLogPlayerEntry();
entry.playername = ap.getPlayer().getName();
entry.classname = ap.getArenaClass().getName();
ArenaPlayerStatistics stats = ap.getStats();
entry.kills = stats.getInt("kills");
entry.dmgDone = stats.getInt("dmgDone");
entry.dmgTaken = stats.getInt("dmgTaken");
entry.swings = stats.getInt("swings");
entry.hits = stats.getInt("hits");
entry.lastWave = stats.getInt("lastWave");
entry.leaveTime = (new Date()).getTime();
return entry;
}
}

View File

@ -0,0 +1,66 @@
package com.garbagemule.MobArena.log;
import java.util.List;
import java.util.Map;
import org.bukkit.inventory.ItemStack;
import com.garbagemule.MobArena.util.MutableInt;
public interface LogSessionBuilder
{
/**
* Builds the start time of this session.
* The method should be called as soon as the session starts, or as soon
* as possible right after for the most precise results.
*/
public void buildStartTime();
/**
* Builds the start time of this session.
* The method should be called as soon as the session ends, or as soon as
* possible right after for the most precise results.
* @param end the start time
*/
public void buildEndTime();
/**
* Builds the duration of this session by creating a duration string on
* the form HH:MM:SS using the provided start and end times.
* PRECONDITION: buildStartTime() and buildEndTime() must be called before
* calling this method.
*/
public void buildDuration();
/**
* Builds the last reached wave of this session.
* @param lastWave the wave number of the last reached wave
*/
public void buildLastWave(int lastWave);
/**
* Builds the number of players that participated in this session.
* @param amount the amount of players
*/
public void buildNumberOfPlayers(int amount);
/**
* Builds the distribution of players over all classes.
* @param classDistribution class names mapped to number of players per class
*/
public void buildClassDistribution(Map<String,MutableInt> classDistribution);
/**
* Builds a player entry when a player has left/died.
* @param entry the log entry to build
* @param rewards a list of rewards given to the player in question
*/
public void buildPlayerEntry(ArenaLogPlayerEntry entry, List<ItemStack> rewards);
/**
* Finalizes the session log, possibly writing it to disk or updating a database.
* The method should only be called when no more changes are expected.
* Behavior is undefined for the other methods after calling this method.
*/
public void finalize();
}

View File

@ -0,0 +1,51 @@
package com.garbagemule.MobArena.log;
import java.util.Map;
import com.garbagemule.MobArena.util.MutableInt;
public interface LogTotalsBuilder
{
/**
* Store the start time of the current session.
* Used to add to the total time played per player.
*/
public void recordStartTime();
/**
* Update the total time played in this arena.
* PRECONDITION: recordStartTime() must have been called first.
*/
public void updateTimePlayed();
/**
* Increment the total number of sessions played.
* The method should be called once per session and no more.
*/
public void updateSessionsPlayed();
/**
* Update the last wave recorded to be the maximum of the current last wave
* and the last wave of the last session.
* @param wave last wave of the last session
*/
public void updateLastWave(int lastWave);
/**
* Update the total distribution of players over all classes.
* @param classDistribution class names mapped to number of players per class
*/
public void updateClassDistribution(Map<String,MutableInt> classDistribution);
/**
* Update the totals for a specific player given a log entry.
* @param entry a log entry
*/
public void updatePlayerEntry(ArenaLogPlayerEntry entry);
/**
* Finish updating the totals. Calling this method makes all changes permanent
* and resets the builder, making it ready for updates for the next session.
*/
public void finish();
}

View File

@ -0,0 +1,111 @@
package com.garbagemule.MobArena.log;
import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.bukkit.inventory.ItemStack;
import com.garbagemule.MobArena.MobArena;
import com.garbagemule.MobArena.util.MutableInt;
import com.garbagemule.MobArena.util.TimeUtils;
import com.garbagemule.MobArena.util.config.Config;
public class YMLSessionBuilder implements LogSessionBuilder
{
private final String GENERAL = "general-info.";
private final String PLAYERS = "players.";
private final String CLASSES = "class-distribution.";
private Config config;
private long start, end;
public YMLSessionBuilder(File file) {
config = new Config(file);
reset();
}
@Override
public void buildStartTime() {
start = new Date().getTime();
config.set(GENERAL + "start-time", TimeUtils.toDateTime(start));
}
@Override
public void buildEndTime() {
end = new Date().getTime();
config.set(GENERAL + "end-time", TimeUtils.toDateTime(end));
}
@Override
public void buildDuration() {
String duration = TimeUtils.toTime(end - start);
config.set(GENERAL + "duration", duration);
}
@Override
public void buildLastWave(int lastWave) {
config.set(GENERAL + "last-wave", lastWave);
}
@Override
public void buildNumberOfPlayers(int amount) {
config.set(GENERAL + "number-of-players", amount);
}
@Override
public void buildClassDistribution(Map<String,MutableInt> classDistribution) {
for (Entry<String,MutableInt> entry : classDistribution.entrySet()) {
int amount = entry.getValue().value();
config.set(CLASSES + entry.getKey(), amount);
}
}
@Override
public void buildPlayerEntry(ArenaLogPlayerEntry entry, List<ItemStack> rewards) {
String path = PLAYERS + entry.playername + ".";
// Name and class
config.set(path + "name", entry.playername);
config.set(path + "class", entry.classname);
// Stats
config.set(path + "kills", entry.kills);
config.set(path + "damage-done", entry.dmgDone);
config.set(path + "damage-taken", entry.dmgTaken);
config.set(path + "swings", entry.swings);
config.set(path + "hits", entry.hits);
config.set(path + "last-wave", entry.lastWave);
config.set(path + "time-played", TimeUtils.toTime(entry.leaveTime - start));
// Rewards
Map<String,MutableInt> summed = new HashMap<String,MutableInt>();
for (ItemStack stack : rewards) {
String type = (stack.getTypeId() == MobArena.ECONOMY_MONEY_ID ? "money" : stack.getType().toString().toLowerCase());
if (!summed.containsKey(type)) {
summed.put(type, new MutableInt());
}
summed.get(type).add(stack.getAmount());
}
for (Entry<String,MutableInt> e : summed.entrySet()) {
config.set(path + "rewards." + e.getKey(), e.getValue().value());
}
}
@Override
public void finalize() {
config.save();
reset();
}
private void reset() {
config.set(GENERAL, null);
config.set(CLASSES, null);
config.set(PLAYERS, null);
}
}

View File

@ -0,0 +1,109 @@
package com.garbagemule.MobArena.log;
import java.io.File;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import com.garbagemule.MobArena.util.MutableInt;
import com.garbagemule.MobArena.util.TimeUtils;
import com.garbagemule.MobArena.util.config.Config;
public class YMLTotalsBuilder implements LogTotalsBuilder
{
private final String GENERAL = "general-info.";
private final String PLAYERS = "players.";
private final String CLASSES = "class-distribution.";
private Config config;
private long start;
public YMLTotalsBuilder(File file) {
config = new Config(file);
if (file.exists()) {
config.load();
}
}
@Override
public void recordStartTime() {
start = new Date().getTime();
}
@Override
public void updateSessionsPlayed() {
String path = GENERAL + "sessions-played";
int games = config.getInt(path, 0);
config.set(path, games + 1);
}
@Override
public void updateTimePlayed() {
long end = new Date().getTime();
String duration = TimeUtils.toTime(end - start);
String path = GENERAL + "time-played";
String old = config.getString(path, "00:00:00");
config.set(path, TimeUtils.addTimes(old, duration));
}
@Override
public void updateLastWave(int lastWave) {
String path = GENERAL + "last-wave";
int old = config.getInt(path, 0);
config.set(path, Math.max(old, lastWave));
}
@Override
public void updateClassDistribution(Map<String, MutableInt> classDistribution) {
for (Entry<String,MutableInt> entry : classDistribution.entrySet()) {
String path = CLASSES + entry.getKey();
int old = config.getInt(path, 0);
int amount = entry.getValue().value();
config.set(path, old + amount);
}
}
@Override
public void updatePlayerEntry(ArenaLogPlayerEntry entry) {
String path = PLAYERS + entry.playername + ".";
// Name and class
config.set(path + "name", entry.playername);
int old = config.getInt(path + "classes." + entry.classname, 0);
config.set(path + "classes." + entry.classname, old + 1);
// All stats
old = config.getInt(path + "kills", 0);
config.set(path + "kills", old + entry.kills);
old = config.getInt(path + "damage-done", 0);
config.set(path + "damage-done", old + entry.dmgDone);
old = config.getInt(path + "damage-taken", 0);
config.set(path + "damage-taken", old + entry.dmgTaken);
old = config.getInt(path + "swings", 0);
config.set(path + "swings", old + entry.swings);
old = config.getInt(path + "hits", 0);
config.set(path + "hits", old + entry.hits);
old = config.getInt(path + "games-played", 0);
config.set(path + "games-played", old + 1);
old = config.getInt(path + "last-wave", 0);
config.set(path + "last-wave", Math.max(old, entry.lastWave));
// Time played
long end = new Date().getTime();
String session = TimeUtils.toTime(end - start);
String played = config.getString(path + "time-played", "00:00:00");
config.set(path + "time-played", TimeUtils.addTimes(played, session));
}
@Override
public void finish() {
config.save();
}
}

View File

@ -0,0 +1,94 @@
package com.garbagemule.MobArena.util;
import java.util.Date;
public class TimeUtils
{
/**
* Turn the input long into a string on the form (D:)HH:MM:SS, where the
* day-part is only added if the number of days is greater than or equal
* to 1, i.e. a long value of 86,399,999.
* @param ms time in milliseconds
* @return string-representation of the input long
*/
public static String toTime(long ms) {
long total = ms / 1000;
long secs = total % 60;
long mins = total % 3600 / 60;
long hours = total / 3600 % 24;
long days = total / 3600 / 24;
String time = (days > 0 ? days + ":" : "") +
(hours < 10 ? "0" + hours : hours) + ":" +
(mins < 10 ? "0" + mins : mins) + ":" +
(secs < 10 ? "0" + secs : secs);
return time;
}
/**
* Makes a new java.util.Date with the input long and toString()s it.
* @param ms time in milliseconds
* @return java.util.Date toString() of the input long
*/
public static String toDateTime(long ms) {
return new Date(ms).toString();
}
/**
* Adds two string-representations of time and returns the resulting time.
* @param t1 a time-string
* @param t2 another time-string
* @return the sum of the time-strings
*/
public static String addTimes(String t1, String t2) {
String[] parts1 = t1.split(":");
String[] parts2 = t2.split(":");
long secs1 = extractSeconds(parts1);
long secs2 = extractSeconds(parts2);
long mins1 = extractMinutes(parts1);
long mins2 = extractMinutes(parts2);
long hours1 = extractHours(parts1);
long hours2 = extractHours(parts2);
long days1 = extractDays(parts1);
long days2 = extractDays(parts2);
long time = (secs1 + secs2 + mins1 + mins2 + hours1 + hours2 + days1 + days2) * 1000;
return toTime(time);
}
private static long extractSeconds(String[] parts) {
int length = parts.length;
if (length < 1) {
return 0L;
}
return Long.parseLong(parts[length - 1]);
}
private static long extractMinutes(String[] parts) {
int length = parts.length;
if (length < 2) {
return 0L;
}
return Long.parseLong(parts[length - 2]) * 60;
}
private static long extractHours(String[] parts) {
int length = parts.length;
if (length < 3) {
return 0L;
}
return Long.parseLong(parts[length - 3]) * 3600;
}
private static long extractDays(String[] parts) {
int length = parts.length;
if (length < 4) {
return 0L;
}
return Long.parseLong(parts[length - 4]) * 24 * 3600;
}
}