Added UserStats and updated leaderboard page

This commit is contained in:
simon 2018-05-11 13:16:34 -04:00
parent 9c41c16079
commit 1678be25c5
8 changed files with 224 additions and 33 deletions

View File

@ -34,10 +34,12 @@ public class VaultExitPortal extends Portal {
@Override
public boolean enter(GameObject object) {
LogManager.LOGGER.info(((ControllableUnit) object).getParent().getUsername() + " Completed vault " +
object.getWorld().getDimension());
if (object instanceof ControllableUnit) {
LogManager.LOGGER.info(((ControllableUnit) object).getParent().getUsername() + " Completed vault " +
object.getWorld().getDimension());
//todo: save vault completion stat
((ControllableUnit) object).getParent().getStats().addToStringSet("completedVaults", getWorld().getDimension());
}
return super.enter(object);
}

View File

@ -14,6 +14,7 @@ import net.simon987.server.logging.LogManager;
import net.simon987.server.plugin.PluginManager;
import net.simon987.server.user.User;
import net.simon987.server.user.UserManager;
import net.simon987.server.user.UserStatsHelper;
import net.simon987.server.websocket.SocketServer;
import java.io.File;
@ -42,14 +43,20 @@ public class GameServer implements Runnable {
private UserManager userManager;
private UserStatsHelper userStatsHelper;
public GameServer() {
this.config = new ServerConfiguration("config.properties");
try{
mongo = new MongoClient("localhost", 27017);
userManager = new UserManager(mongo, config);
DB db = mongo.getDB(config.getString("mongo_dbname"));
DBCollection userCollection = db.getCollection("user");
userManager = new UserManager(userCollection);
userStatsHelper = new UserStatsHelper(userCollection);
} catch (UnknownHostException e) {
e.printStackTrace();
}
@ -74,7 +81,6 @@ public class GameServer implements Runnable {
if (pluginFile.getName().endsWith(".jar")) {
pluginManager.load(pluginFile, config);
}
}
} else {
if (!pluginDir.mkdir()) {
@ -98,7 +104,7 @@ public class GameServer implements Runnable {
eventDispatcher.getListeners().add(new HealObjCommandListener());
eventDispatcher.getListeners().add(new DamageObjCommandListener());
eventDispatcher.getListeners().add(new SetEnergyCommandListener());
eventDispatcher.getListeners().add(new SaveGameCommandListener());
}
public GameUniverse getGameUniverse() {
@ -141,10 +147,7 @@ public class GameServer implements Runnable {
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void tick() {
@ -230,7 +233,7 @@ public class GameServer implements Runnable {
" | U:" + GameServer.INSTANCE.getGameUniverse().getUserCount());
}
private void save() {
public void save() {
LogManager.LOGGER.info("Saving to MongoDB | W:" + gameUniverse.getWorldCount() + " | U:" + gameUniverse.getUserCount());
try{
@ -294,4 +297,8 @@ public class GameServer implements Runnable {
public UserManager getUserManager() {
return userManager;
}
public UserStatsHelper getUserStatsHelper() {
return userStatsHelper;
}
}

View File

@ -28,6 +28,8 @@ public class User implements MongoSerialisable {
private boolean guest = false;
private boolean moderator = false;
private UserStats stats;
public User() throws CancelledException {
GameEvent event = new UserCreationEvent(this);
GameServer.INSTANCE.getEventDispatcher().dispatch(event);
@ -35,6 +37,7 @@ public class User implements MongoSerialisable {
throw new CancelledException();
}
this.stats = new UserStats();
}
public User(ControllableUnit unit) {
@ -53,6 +56,7 @@ public class User implements MongoSerialisable {
dbObject.put("cpu", cpu.mongoSerialise());
dbObject.put("password", password);
dbObject.put("moderator", moderator);
dbObject.put("stats", stats.mongoSerialise());
return dbObject;
@ -65,6 +69,7 @@ public class User implements MongoSerialisable {
user.userCode = (String) obj.get("code");
user.password = (String) obj.get("password");
user.moderator = (boolean) obj.get("moderator");
user.stats = new UserStats((BasicDBObject) obj.get("stats"));
user.getControlledUnit().setParent(user);
@ -72,7 +77,6 @@ public class User implements MongoSerialisable {
return user;
}
//----
public String getUserCode() {
return userCode;
@ -133,4 +137,8 @@ public class User implements MongoSerialisable {
public void setModerator(boolean moderator) {
this.moderator = moderator;
}
public UserStats getStats() {
return stats;
}
}

View File

@ -1,8 +1,10 @@
package net.simon987.server.user;
import com.mongodb.*;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import net.simon987.server.GameServer;
import net.simon987.server.ServerConfiguration;
import net.simon987.server.assembly.exception.CancelledException;
import net.simon987.server.crypto.RandomStringGenerator;
import net.simon987.server.logging.LogManager;
@ -12,14 +14,11 @@ import java.util.ArrayList;
public class UserManager {
private MongoClient mongo;
private DBCollection userCollection;
public UserManager(MongoClient mongo, ServerConfiguration config) {
public UserManager(DBCollection userCollection) {
this.mongo = mongo;
DB db = mongo.getDB(config.getString("mongo_dbname"));
userCollection = db.getCollection("user");
this.userCollection = userCollection;
}
/**

View File

@ -0,0 +1,98 @@
package net.simon987.server.user;
import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import net.simon987.server.io.MongoSerialisable;
import net.simon987.server.logging.LogManager;
public class UserStats implements MongoSerialisable {
private BasicDBObject stats;
public UserStats() {
this.stats = new BasicDBObject();
}
public UserStats(BasicDBObject stats) {
this.stats = stats;
}
@Override
public BasicDBObject mongoSerialise() {
return stats;
}
/**
* Increment a stat n times
*
* @param name Name of the stat to increment
* @param count Number of time to increment
*/
public void incrementStat(String name, int count) {
stats.putIfAbsent(name, 0);
stats.put(name, stats.getInt(name) + count);
}
/**
* Set the value of a stat
*
* @param name Name of the stat
* @param value new value
*/
public void setInt(String name, int value) {
stats.put(name, value);
}
/**
* Get the value of at stat
*
* @param name Name of the value
* @return The value of the stat. Returns 0 if not found
*/
public int getInt(String name) {
return stats.getInt(name, 0);
}
/**
* Add an string item to a set
*
* @param name Name of the stat
* @param value Value to add to the set
*/
public void addToStringSet(String name, String value) {
stats.putIfAbsent(name, new BasicDBList());
try {
((BasicDBList) stats.get(name)).add(value);
} catch (ClassCastException e) {
LogManager.LOGGER.severe("UserStats: cannot add to list because stat already exists and is not a list");
}
}
/**
* Remove an item from a set
*
* @param name Name of the stat
* @param value Value to remove from the set
* @return true if the list contained the item
*/
public boolean removeFromSet(String name, String value) {
if (stats.putIfAbsent(name, new BasicDBList()) != null) {
return ((BasicDBList) stats.get(name)).remove(value);
}
return false;
}
public BasicDBList getSet(String name) {
stats.putIfAbsent(name, new BasicDBList());
return (BasicDBList) stats.get(name);
}
}

View File

@ -0,0 +1,82 @@
package net.simon987.server.user;
import com.mongodb.*;
import net.simon987.server.GameServer;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Map;
/**
* Retrieve user stats in a structured fashion
*/
public class UserStatsHelper {
/**
* Database collection of users
*/
private DBCollection users;
/**
* @param users Database collection of users
*/
public UserStatsHelper(DBCollection users) {
this.users = users;
}
/**
* Get top n players along with their stat value, in descending order
*
* @param statName Name of the stat
* @param n Maximum number of players
* @return Top n players, in User,value format, in descending order
*/
public ArrayList<Map.Entry<User, Integer>> getTopN(String statName, int n) {
ArrayList<Map.Entry<User, Integer>> rows = new ArrayList<>();
BasicDBObject orderBy = new BasicDBObject("$stats." + statName, -1);
DBCursor cursor = users.find().sort(orderBy).limit(n);
while (cursor.hasNext()) {
DBObject dbUser = cursor.next();
User user = GameServer.INSTANCE.getGameUniverse().getUser((String) dbUser.get("username"));
rows.add(new AbstractMap.SimpleEntry<>(user, user.getStats().getInt(statName)));
}
return rows;
}
/**
* Get top n players along with the stat set, in descending order
*
* @param statName Name of the stat
* @param n Maximum number of players
* @return Top n players, in User,set format, in descending order
*/
public ArrayList<Map.Entry<User, BasicDBList>> getTopNSetLength(String statName, int n) {
ArrayList<Map.Entry<User, BasicDBList>> rows = new ArrayList<>();
BasicDBList ifNullList = new BasicDBList();
ifNullList.add("$stats." + statName);
ifNullList.add(new BasicDBList());
BasicDBObject project = new BasicDBObject();
project.put("setLength", new BasicDBObject("$size", new BasicDBObject("$ifNull", ifNullList)));
project.put("username", 1);
Iterable<DBObject> results = users.aggregate(
new BasicDBObject("$project", project),
new BasicDBObject("$sort", new BasicDBObject("setLength", -1)),
new BasicDBObject("$limit", n)
).results();
for (DBObject dbUser : results) {
User user = GameServer.INSTANCE.getGameUniverse().getUser((String) dbUser.get("username"));
rows.add(new AbstractMap.SimpleEntry<>(user, user.getStats().getSet(statName)));
}
return rows;
}
}

View File

@ -1,5 +1,6 @@
package net.simon987.server.web;
import net.simon987.server.GameServer;
import spark.ModelAndView;
import spark.Request;
import spark.Response;
@ -12,9 +13,9 @@ public class LeaderBoardPage implements TemplateViewRoute {
@Override
public ModelAndView handle(Request request, Response response) {
Map<String, Object> model = new HashMap<>(1);
Map<String, Object> model = new HashMap<>(2);
model.put("session", request.session());
model.put("stats", GameServer.INSTANCE.getUserStatsHelper().getTopNSetLength("completedVaults", 25));
return new ModelAndView(model, "leaderboard.vm");
}
}
}

View File

@ -19,18 +19,12 @@
</tr>
</thead>
<tbody>
<tr>
<td>Test1</td>
<td>Test2</td>
</tr>
<tr>
<td>Test1</td>
<td>Test2</td>
</tr>
<tr>
<td>Test1</td>
<td>Test2</td>
</tr>
#foreach($row in $stats)
<tr>
<td>$row.getKey().getUsername()</td>
<td>$row.getValue().size()</td>
</tr>
#end
</tbody>
</table>
</div>