diff --git a/src/main/java/com/buttongames/butterfly/hibernate/dao/impl/ddr16/UserSongRecordDao.java b/src/main/java/com/buttongames/butterfly/hibernate/dao/impl/ddr16/UserSongRecordDao.java
index 3509f8a..5c4f26f 100644
--- a/src/main/java/com/buttongames/butterfly/hibernate/dao/impl/ddr16/UserSongRecordDao.java
+++ b/src/main/java/com/buttongames/butterfly/hibernate/dao/impl/ddr16/UserSongRecordDao.java
@@ -11,6 +11,7 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import java.time.LocalDateTime;
+import java.util.List;
/**
* DAO for interacting with UserSongRecord objects in the database.
@@ -63,4 +64,20 @@ public class UserSongRecordDao extends AbstractHibernateDao {
this.closeCurrentSession();
return result;
}
+
+ /**
+ * Finds all song records for a user.
+ * @param user The user of the records
+ * @return A list of matching records
+ */
+ public List findByUser(final UserProfile user) {
+ this.openCurrentSession();
+
+ final Query query = this.currentSession.createQuery("from UserSongRecord where user = :user");
+ query.setParameter("user", user);
+ final List result = query.getResultList();
+
+ this.closeCurrentSession();
+ return result;
+ }
}
diff --git a/src/main/java/com/buttongames/butterfly/http/ButterflyHttpServer.java b/src/main/java/com/buttongames/butterfly/http/ButterflyHttpServer.java
index b2b5689..de78b3e 100644
--- a/src/main/java/com/buttongames/butterfly/http/ButterflyHttpServer.java
+++ b/src/main/java/com/buttongames/butterfly/http/ButterflyHttpServer.java
@@ -74,7 +74,6 @@ public class ButterflyHttpServer {
private static final ImmutableSet SUPPORTED_MODULES;
// Do a static setup of our supported models, modules, etc.
- // TODO: Make this not hardcoded
static {
SUPPORTED_MODELS = ImmutableSet.of("mdx_2018042300");
SUPPORTED_MODULES = ImmutableSet.of("services", "pcbtracker", "message", "facility", "pcbevent",
@@ -185,7 +184,6 @@ public class ButterflyHttpServer {
/**
* Configures the routes on the server, and the exception handlers.
- * TODO: Remove all the hardcoded stuff.
*/
private void configureRoutesAndExceptions() {
// configure our root route; its handler will parse the request and go from there
diff --git a/src/main/java/com/buttongames/butterfly/http/handlers/impl/PlayerDataRequestHandler.java b/src/main/java/com/buttongames/butterfly/http/handlers/impl/PlayerDataRequestHandler.java
index b877a75..522a299 100644
--- a/src/main/java/com/buttongames/butterfly/http/handlers/impl/PlayerDataRequestHandler.java
+++ b/src/main/java/com/buttongames/butterfly/http/handlers/impl/PlayerDataRequestHandler.java
@@ -50,7 +50,9 @@ import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
@@ -329,7 +331,7 @@ public class PlayerDataRequestHandler extends BaseRequestHandler {
// we need to return the top score for every song/difficulty
for (Song song : SONGS_2018042300) {
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < 9; i++) {
if (GLOBAL_HIGH_SCORES_CACHE.get(song.getMcode()).containsKey(i)) {
record = GLOBAL_HIGH_SCORES_CACHE.get(song.getMcode()).get(i);
@@ -362,13 +364,89 @@ public class PlayerDataRequestHandler extends BaseRequestHandler {
throw new UnsupportedRequestException();
}
- // TODO: Implement this properly and load/save scores... also, events probably isn't a static response
KXmlBuilder respBuilder = KXmlBuilder.create("response")
.e("playerdata")
.s32("result", 0).up()
.bool("is_new", false).up();
- // insert the events
+ // load user scores if this was for a particular user
+ if (!refId.equals("X0000000000000000000000000000000")) {
+ // get the user's scores and sort them out so we can get the top scores
+ // for each song/difficulty
+ final List userRecords =
+ this.songRecordDao.findByUser(
+ this.profileDao.findByUser(
+ this.cardDao.findByRefId(refId).getUser()));
+
+ // sort them by song and difficulty, then insert them into the response
+ // key for top map is the song ID
+ // key for the 2nd map is the difficulty
+ // the array: a[0] = count, a[1] = top UserSongRecord
+ final HashMap> userTopScores = new HashMap<>();
+
+ for (UserSongRecord record : userRecords) {
+ if (!userTopScores.containsKey(record.getSongId())) {
+ userTopScores.put(record.getSongId(), new HashMap<>());
+ userTopScores.get(record.getSongId()).put(record.getNoteType(), new Object[] { 1, record });
+ } else {
+ if (!userTopScores.get(record.getSongId()).containsKey(record.getNoteType())) {
+ userTopScores.get(record.getSongId()).put(record.getNoteType(), new Object[] { 1, record });
+ } else {
+ Object[] currRecord = userTopScores.get(record.getSongId()).get(record.getNoteType());
+ currRecord[0] = ((Integer) currRecord[0]) + 1;
+
+ if (((UserSongRecord) currRecord[1]).getScore() < record.getScore()) {
+ currRecord[1] = record;
+ }
+
+ userTopScores.get(record.getSongId()).put(record.getNoteType(), currRecord);
+ }
+ }
+ }
+
+ int count = 0;
+ int rank = 0;
+ int clearkind = 0;
+ int score = 0;
+ int ghostid = 0;
+
+ // insert them into the response
+ for (Map.Entry> entry : userTopScores.entrySet()) {
+ respBuilder = respBuilder.e("music")
+ .u32("mcode", entry.getKey()).up();
+
+ // iterate through each difficulty
+ for (int i = 0; i < 9; i++) {
+ if (entry.getValue().containsKey(i)) {
+ Object[] record = entry.getValue().get(i);
+ UserSongRecord topRecord = (UserSongRecord) record[1];
+
+ count = (Integer) record[0];
+ rank = topRecord.getRank();
+ clearkind = topRecord.getClearKind();
+ score = topRecord.getScore();
+ ghostid = ((Long) topRecord.getGhostData().getId()).intValue();
+ } else {
+ count = 0;
+ rank = 0;
+ clearkind = 0;
+ score = 0;
+ ghostid = 0;
+ }
+
+ respBuilder = respBuilder.e("note")
+ .u16("count", count).up()
+ .u8("rank", rank).up()
+ .u8("clearkind", clearkind).up()
+ .s32("score", score).up()
+ .s32("ghostid", ghostid).up().up();
+ }
+
+ respBuilder = respBuilder.up();
+ }
+ }
+
+ // TODO: Events probably isn't a static response
final Document document = respBuilder.getDocument();
final Element elem = respBuilder.getElement();
@@ -797,11 +875,21 @@ public class PlayerDataRequestHandler extends BaseRequestHandler {
* @return A response object for Spark
*/
private Object handleGhostLoadRequest(final int ghostId, final Request request, final Response response) {
- // TODO: Store and load ghost data correctly
- final KXmlBuilder builder = KXmlBuilder.create("response")
+ KXmlBuilder builder = KXmlBuilder.create("response")
.e("playerdata")
.s32("result", 0).up();
+ final GhostData ghostData = this.ghostDataDao.findById((long) ghostId);
+
+ if (ghostData != null) {
+ builder = builder.e("ghostdata")
+ .s32("code", 0).up()
+ .u32("mcode", ghostData.getMcode()).up()
+ .u8("notetype", ghostData.getNoteType()).up()
+ .s32("ghostsize", ghostData.getGhostData().length()).up()
+ .str("ghost", ghostData.getGhostData());
+ }
+
return this.sendResponse(request, response, builder);
}
@@ -918,7 +1006,7 @@ public class PlayerDataRequestHandler extends BaseRequestHandler {
int folder = XmlUtils.intAtChild(recordNode, "folder");
// construct and save
- GhostData newGhostData = new GhostData(user, ghostStr);
+ GhostData newGhostData = new GhostData(user, ghostStr, songId, noteType);
this.ghostDataDao.create(newGhostData);
UserSongRecord newRecord = new UserSongRecord(user, playSide, playStyle, area, weight100, shopName, isPremium,
diff --git a/src/main/java/com/buttongames/butterfly/model/ddr16/GhostData.java b/src/main/java/com/buttongames/butterfly/model/ddr16/GhostData.java
index 9455dcd..e944a46 100644
--- a/src/main/java/com/buttongames/butterfly/model/ddr16/GhostData.java
+++ b/src/main/java/com/buttongames/butterfly/model/ddr16/GhostData.java
@@ -37,11 +37,21 @@ public class GhostData implements Externalizable {
@Column(name = "ghost_data", columnDefinition = "TEXT")
private String ghostData;
+ /** The mcode of the song for this data */
+ @Column(name = "mcode")
+ private int mcode;
+
+ /** The difficulty the ghost data was for */
+ @Column(name = "note_type")
+ private int noteType;
+
public GhostData() { }
- public GhostData(UserProfile user, String ghostData) {
+ public GhostData(UserProfile user, String ghostData, int mcode, int noteType) {
this.user = user;
this.ghostData = ghostData;
+ this.mcode = mcode;
+ this.noteType = noteType;
}
@Override
@@ -49,6 +59,8 @@ public class GhostData implements Externalizable {
out.writeLong(this.id);
out.writeObject(this.user);
out.writeUTF(this.ghostData);
+ out.writeInt(this.mcode);
+ out.writeInt(this.noteType);
}
@Override
@@ -56,6 +68,8 @@ public class GhostData implements Externalizable {
this.setId(in.readLong());
this.setUser((UserProfile) in.readObject());
this.setGhostData(in.readUTF());
+ this.setMcode(in.readInt());
+ this.setNoteType(in.readInt());
}
public long getId() {
@@ -81,4 +95,20 @@ public class GhostData implements Externalizable {
public void setGhostData(String ghostData) {
this.ghostData = ghostData;
}
+
+ public int getMcode() {
+ return mcode;
+ }
+
+ public void setMcode(int mcode) {
+ this.mcode = mcode;
+ }
+
+ public int getNoteType() {
+ return noteType;
+ }
+
+ public void setNoteType(int noteType) {
+ this.noteType = noteType;
+ }
}