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 6ea15b3..b877a75 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 @@ -52,6 +52,7 @@ import java.util.Arrays; import java.util.Base64; import java.util.List; import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; /** * Handler for any requests that come to the playerdata module. @@ -136,6 +137,11 @@ public class PlayerDataRequestHandler extends BaseRequestHandler { */ private static List SONGS_2018042300; + /** + * In-memory cache of the global high scores. + */ + private static ConcurrentHashMap> GLOBAL_HIGH_SCORES_CACHE; + static { loadEvents(); loadMusicDb(); @@ -148,6 +154,9 @@ public class PlayerDataRequestHandler extends BaseRequestHandler { this.profileDao = profileDao; this.ghostDataDao = ghostDataDao; this.songRecordDao = songRecordDao; + + // cache the global high scores + this.loadGlobalHighScores(); } /** @@ -191,6 +200,30 @@ public class PlayerDataRequestHandler extends BaseRequestHandler { } } + /** + * Loads the global high scores into memory so we can use this cache for the + * high scores requests and not hit the DB every time. + */ + private void loadGlobalHighScores() { + GLOBAL_HIGH_SCORES_CACHE = new ConcurrentHashMap<>(); + + UserSongRecord record; + + // we need to return the top score for every song/difficulty + for (Song song : SONGS_2018042300) { + // create the internal maps now + GLOBAL_HIGH_SCORES_CACHE.put(song.getMcode(), new ConcurrentHashMap<>()); + + for (int i = 0; i < 8; i++) { + record = this.songRecordDao.findTopScoreForSongDifficulty(song.getMcode(), i); + + if (record != null) { + GLOBAL_HIGH_SCORES_CACHE.get(song.getMcode()).put(i, record); + } + } + } + } + /** * Handles an incoming request for the playerdata module. * @param requestBody The XML document of the incoming request. @@ -297,9 +330,9 @@ 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++) { - record = this.songRecordDao.findTopScoreForSongDifficulty(song.getMcode(), i); + if (GLOBAL_HIGH_SCORES_CACHE.get(song.getMcode()).containsKey(i)) { + record = GLOBAL_HIGH_SCORES_CACHE.get(song.getMcode()).get(i); - if (record != null) { respBuilder = respBuilder.e("record") .u32("mcode", song.getMcode()).up() .u8("notetype", i).up() @@ -897,6 +930,14 @@ public class PlayerDataRequestHandler extends BaseRequestHandler { showFastSlow, songBaseName, songTitle, songArtist, bpmMin, bpmMax, level, series, bemaniFlag, genreFlag, limited, region, grVoltage, grStream, grChaos, grFreeze, grAir, share, endtime, folder); this.songRecordDao.create(newRecord); + + // make sure we don't also need to update the global high score cache + ConcurrentHashMap songRecords = GLOBAL_HIGH_SCORES_CACHE.get(songId); + + if (!songRecords.containsKey(noteType) || + songRecords.get(noteType).getScore() < score) { + GLOBAL_HIGH_SCORES_CACHE.get(songId).put(noteType, newRecord); + } } final KXmlBuilder builder = KXmlBuilder.create("response")