-
Notifications
You must be signed in to change notification settings - Fork 121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filter beatmap sets based on conditional searches (eg: AR>9) #323
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,8 @@ public class BeatmapSet implements Iterable<Beatmap> { | |
/** List of associated beatmaps. */ | ||
private final ArrayList<Beatmap> beatmaps; | ||
|
||
/** Search filter */ | ||
private ArrayList<Beatmap> filteredBeatmaps = new ArrayList<>(); | ||
/** | ||
* Constructor. | ||
* @param beatmaps the beatmaps in this set | ||
|
@@ -43,24 +45,35 @@ public BeatmapSet(ArrayList<Beatmap> 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(); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you conditionally return the unfiltered size here -- wouldn't that cause problems? (But check that it doesn't break things if you remove it.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the moment how it is written is that filtered list starts off empty, and then maps are added to the filter. If the filter list is empty then it is assumed no filter is applied so therefore the unfiltered size should be returned, else other parts of the program will think there's no maps at all. I can change it so that instead filteredBeatmaps is a clone of beatmaps at first and then remove maps based on the criteria, that way it can always return filteredBeatmaps.size/get |
||
|
||
/** | ||
* Returns the true number of elements | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
public int trueSize(){return beatmaps.size(); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would prefer a more meaningful name like |
||
|
||
/** | ||
* 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); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, why would we want the unfiltered |
||
|
||
/** | ||
* Removes the beatmap at the given index. | ||
* @param index the beatmap index | ||
* @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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't we also want to remove the beatmap from the unfiltered list too? (Wouldn't this cause the deleted beatmap to reappear when the filter is reset?) |
||
} | ||
return beatmaps.remove(index); | ||
} | ||
|
||
@Override | ||
public Iterator<Beatmap> iterator() { return beatmaps.iterator(); } | ||
|
@@ -78,7 +91,7 @@ public BeatmapSet(ArrayList<Beatmap> 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
float speedModifier = GameMod.getSpeedMultiplier(); | ||
long endTime = (long) (beatmap.endTime / speedModifier); | ||
int bpmMin = (int) (beatmap.bpmMin * speedModifier); | ||
|
@@ -116,13 +129,20 @@ 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
public void clearFilter(){ | ||
filteredBeatmaps.clear();} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix the formatting here. :P |
||
|
||
/** | ||
* Checks whether the beatmap set matches a given search query. | ||
* @param query the search term | ||
* @return true if title, artist, creator, source, version, or tag matches query | ||
*/ | ||
public boolean matches(String query) { | ||
// search: title, artist, creator, source, version, tags (first beatmap) | ||
filteredBeatmaps.clear(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could write a (very similar) method |
||
found = true; | ||
} | ||
|
||
return false; | ||
} | ||
return found; | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,6 +60,9 @@ public class BeatmapSetList { | |
/** Current list of nodes (subset of parsedNodes, used for searches). */ | ||
private ArrayList<BeatmapSetNode> nodes; | ||
|
||
/** nodes in last search, used to reset conditional search matches */ | ||
private ArrayList<BeatmapSetNode> lastSearchNodes; | ||
|
||
/** Set of all beatmap set IDs for the parsed beatmaps. */ | ||
private HashSet<Integer> 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(){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the sake of clarity, I think it's better to just call Alternatively, since |
||
//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<String> terms = new LinkedList<String>(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(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returns the number of elements (possibly filtered).