From 746c711e041ef22d4e5b6126c286c6c38102f79c Mon Sep 17 00:00:00 2001 From: Aaron Date: Sat, 14 Oct 2017 10:52:27 +1100 Subject: [PATCH] Filter beatmap sets based on conditional searches (eg: AR>9) --- src/itdelatrisu/opsu/beatmap/BeatmapSet.java | 42 +++++++++++++++---- .../opsu/beatmap/BeatmapSetList.java | 26 +++++++++++- src/itdelatrisu/opsu/states/ButtonMenu.java | 2 +- 3 files changed, 58 insertions(+), 12 deletions(-) diff --git a/src/itdelatrisu/opsu/beatmap/BeatmapSet.java b/src/itdelatrisu/opsu/beatmap/BeatmapSet.java index 365c9983..bb11f820 100644 --- a/src/itdelatrisu/opsu/beatmap/BeatmapSet.java +++ b/src/itdelatrisu/opsu/beatmap/BeatmapSet.java @@ -34,6 +34,8 @@ public class BeatmapSet implements Iterable { /** List of associated beatmaps. */ private final ArrayList beatmaps; + /** Search filter */ + private ArrayList filteredBeatmaps = new ArrayList<>(); /** * Constructor. * @param beatmaps the beatmaps in this set @@ -43,16 +45,21 @@ public BeatmapSet(ArrayList beatmaps) { } /** - * Returns the number of elements. + * Returns the number of search results or total number. */ - public int size() { return beatmaps.size(); } + public int size() { return filteredBeatmaps.size() > 0 ? filteredBeatmaps.size() : beatmaps.size(); } + + /** + * Returns the true number of elements + */ + public int trueSize(){return beatmaps.size(); } /** * Returns the beatmap at the given index. * @param index the beatmap index * @throws IndexOutOfBoundsException if the index is out of range */ - public Beatmap get(int index) { return beatmaps.get(index); } + public Beatmap get(int index) { return filteredBeatmaps.size() > 0 ? filteredBeatmaps.get(index) : beatmaps.get(index); } /** * Removes the beatmap at the given index. @@ -60,7 +67,13 @@ public BeatmapSet(ArrayList beatmaps) { * @return the removed beatmap * @throws IndexOutOfBoundsException if the index is out of range */ - public Beatmap remove(int index) { return beatmaps.remove(index); } + public Beatmap remove(int index) { + if(filteredBeatmaps.size() > 0){ + beatmaps.remove(this.get(index)); + return filteredBeatmaps.remove(index); + } + return beatmaps.remove(index); + } @Override public Iterator iterator() { return beatmaps.iterator(); } @@ -78,7 +91,7 @@ public BeatmapSet(ArrayList beatmaps) { * @throws IndexOutOfBoundsException if the index is out of range */ public String[] getInfo(int index) { - Beatmap beatmap = beatmaps.get(index); + Beatmap beatmap = this.get(index); float speedModifier = GameMod.getSpeedMultiplier(); long endTime = (long) (beatmap.endTime / speedModifier); int bpmMin = (int) (beatmap.bpmMin * speedModifier); @@ -116,6 +129,12 @@ public String toString() { return String.format("%s - %s", beatmap.getArtist(), beatmap.getTitle()); } + /** + * Clears the search array so we correctly reset the set after changing a filter + */ + public void clearFilter(){ + filteredBeatmaps.clear();} + /** * Checks whether the beatmap set matches a given search query. * @param query the search term @@ -123,6 +142,7 @@ public String toString() { */ public boolean matches(String query) { // search: title, artist, creator, source, version, tags (first beatmap) + filteredBeatmaps.clear(); Beatmap beatmap = beatmaps.get(0); if (beatmap.title.toLowerCase().contains(query) || beatmap.titleUnicode.toLowerCase().contains(query) || @@ -153,6 +173,8 @@ public boolean matches(String query) { * @return true if the condition is met */ public boolean matches(String type, String operator, float value) { + filteredBeatmaps.clear(); + boolean found = false; for (Beatmap beatmap : beatmaps) { // get value float v; @@ -180,11 +202,13 @@ public boolean matches(String type, String operator, float value) { default: return false; } - if (met) - return true; - } + if (met){ + filteredBeatmaps.add(beatmap); + found = true; + } - return false; + } + return found; } /** diff --git a/src/itdelatrisu/opsu/beatmap/BeatmapSetList.java b/src/itdelatrisu/opsu/beatmap/BeatmapSetList.java index f066763c..c8882c74 100644 --- a/src/itdelatrisu/opsu/beatmap/BeatmapSetList.java +++ b/src/itdelatrisu/opsu/beatmap/BeatmapSetList.java @@ -60,6 +60,9 @@ public class BeatmapSetList { /** Current list of nodes (subset of parsedNodes, used for searches). */ private ArrayList nodes; + /** nodes in last search, used to reset conditional search matches */ + private ArrayList lastSearchNodes; + /** Set of all beatmap set IDs for the parsed beatmaps. */ private HashSet MSIDdb; @@ -100,12 +103,26 @@ private BeatmapSetList() { * This does not erase any parsed nodes. */ public void reset() { + resetFiltered(); nodes = groupNodes = BeatmapGroup.current().filter(parsedNodes); expandedIndex = -1; expandedStartNode = expandedEndNode = null; lastQuery = null; } + /** + * Will clear the filter on any mapsets that matched the last search request + */ + private void resetFiltered(){ + //Reset any nodes we filtered maps for + if(lastSearchNodes != null){ + for(BeatmapSetNode n : lastSearchNodes) + n.getBeatmapSet().clearFilter(); + //This is most likely going to be referencing nodes therefore we don't want to clear it + lastSearchNodes = new ArrayList<>(); + } + } + /** * Returns the number of elements. */ @@ -172,7 +189,7 @@ else if (ePrev != null && ePrev.index == expandedIndex) nodes.remove(index); parsedNodes.remove(eCur); groupNodes.remove(eCur); - mapCount -= beatmapSet.size(); + mapCount -= beatmapSet.trueSize(); if (beatmap.beatmapSetID > 0) MSIDdb.remove(beatmap.beatmapSetID); for (Beatmap bm : beatmapSet) { @@ -237,7 +254,7 @@ public boolean deleteSong(BeatmapSetNode node) { // last song in group? int size = node.getBeatmapSet().size(); - if (size == 1) + if (node.getBeatmapSet().trueSize() == 1) return deleteSongGroup(node); // reset indices @@ -446,6 +463,9 @@ public boolean search(String query) { lastQuery = query; LinkedList terms = new LinkedList(Arrays.asList(query.split("\\s+"))); + //Reset any map sets we previously filtered maps in + resetFiltered(); + // if empty query, reset to original list if (query.isEmpty() || terms.isEmpty()) { nodes = groupNodes; @@ -480,6 +500,8 @@ public boolean search(String query) { if (node.getBeatmapSet().matches(type, operator, value)) nodes.add(node); } + //theres no need to store a normal search as beatmaps wont be filtered at all and therefore won't need to be reset + lastSearchNodes = nodes; } else { // normal term String term = terms.remove(); diff --git a/src/itdelatrisu/opsu/states/ButtonMenu.java b/src/itdelatrisu/opsu/states/ButtonMenu.java index e8a549f5..98b15cc4 100644 --- a/src/itdelatrisu/opsu/states/ButtonMenu.java +++ b/src/itdelatrisu/opsu/states/ButtonMenu.java @@ -488,7 +488,7 @@ public void click(GameContainer container, StateBasedGame game) { public void click(GameContainer container, StateBasedGame game) { SoundController.playSound(SoundEffect.MENUHIT); BeatmapSetNode node = ((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).getNode(); - MenuState ms = (node.beatmapIndex == -1 || node.getBeatmapSet().size() == 1) ? + MenuState ms = (node.beatmapIndex == -1 || node.getBeatmapSet().trueSize() == 1) ? MenuState.BEATMAP_DELETE_CONFIRM : MenuState.BEATMAP_DELETE_SELECT; ((ButtonMenu) game.getState(Opsu.STATE_BUTTONMENU)).setMenuState(ms, node); game.enterState(Opsu.STATE_BUTTONMENU);