1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 05:42:56 +08:00

Replace regex with a custom algorithm and update test scene.

This commit is contained in:
Pasi4K5 2023-09-29 13:44:42 +02:00
parent 23c20ca5f4
commit c927f90a48
2 changed files with 71 additions and 24 deletions

View File

@ -19,7 +19,7 @@ namespace osu.Game.Tests.SongSelect
("Title1", "Diff2"),
("My[Favourite]Song", "Expert"),
("Title", "My Favourite Diff"),
("Another One", "diff ]with [[] brackets]]]"),
("Another One", "diff ]with [[ brackets]]]"),
};
[TestCase("[1]", new[] { 0 })]
@ -34,7 +34,8 @@ namespace osu.Game.Tests.SongSelect
[TestCase("Title1 [Diff]", new[] { 0, 1 })]
[TestCase("Title1[Diff]", new int[] { })]
[TestCase("[diff ]with]", new[] { 4 })]
[TestCase("[diff ]with [[] brackets]]]]", new[] { 4 })]
[TestCase("[diff ]with [[ brackets]]]]", new[] { 4 })]
[TestCase("[diff] another [brackets]", new[] { 4 })]
public void TestDifficultySearch(string query, int[] expectedBeatmapIndexes)
{
var carouselBeatmaps = createCarouselBeatmaps().ToList();

View File

@ -19,30 +19,9 @@ namespace osu.Game.Screens.Select
@"\b(?<key>\w+)(?<op>(:|=|(>|<)(:|=)?))(?<value>("".*""[!]?)|(\S*))",
RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex difficulty_query_syntax_regex = new Regex(
@"(\s|^)((\[(?>\[(?<level>)|[^[\]]+|\](?<-level>))*(?(level)(?!))\](\s|$))|(\[.*))",
RegexOptions.Compiled);
internal static void ApplyQueries(FilterCriteria criteria, string query)
{
while (true)
{
var match = difficulty_query_syntax_regex.Matches(query).FirstOrDefault();
if (match is null) break;
// Trim the first character because it's always '[' (ignoring spaces)
string cleanDifficultyQuery = match.Value.Trim(' ')[1..];
if (cleanDifficultyQuery.EndsWith(']'))
cleanDifficultyQuery = cleanDifficultyQuery[..^1];
criteria.DifficultySearchText = cleanDifficultyQuery;
// Insert whitespace if necessary so that the words before and after the difficulty query aren't joined together.
bool insertWhitespace = match.Value.StartsWith(' ') && match.Value.EndsWith(' ');
query = query.Replace(match.Value, insertWhitespace ? " " : "");
}
criteria.DifficultySearchText = extractDifficultySearchText(ref query);
foreach (Match match in query_syntax_regex.Matches(query))
{
@ -57,6 +36,73 @@ namespace osu.Game.Screens.Select
criteria.SearchText = query;
}
/// <summary>
/// Extracts and returns the difficulty search text between square brackets.
/// </summary>
/// <param name="query">The search query. The difficulty search text will be removed from the query.</param>
/// <returns>The difficulty search text (without the square brackets).</returns>
private static string extractDifficultySearchText(ref string query)
{
var openingBracketIndexes = new List<int>();
var closingBracketIndexes = new List<int>();
populateIndexLists(ref query);
return performExtraction(ref query);
void populateIndexLists(ref string query)
{
bool currentlyBetweenBrackets = false;
for (int i = 0; i < query.Length; i++)
{
switch (query[i])
{
case '[' when !currentlyBetweenBrackets && (i == 0 || query[i - 1] == ' '):
currentlyBetweenBrackets = true;
openingBracketIndexes.Add(i + 1);
break;
case ']' when currentlyBetweenBrackets && (i == query.Length - 1 || query[i + 1] == ' '):
currentlyBetweenBrackets = false;
closingBracketIndexes.Add(i);
break;
}
}
if (currentlyBetweenBrackets)
{
// If there is no "]" closing the current difficulty search query, append it.
query += ']';
closingBracketIndexes.Add(query.Length - 1);
}
}
string performExtraction(ref string query)
{
var searchTexts = new List<string>();
string originalQuery = query;
for (int i = 0; i < openingBracketIndexes.Count; i++)
{
int startIndex = openingBracketIndexes[i];
int endIndex = closingBracketIndexes[i];
string searchText = originalQuery[startIndex..endIndex];
searchTexts.Add(searchText);
query = query
.Replace($" [{searchText}]", "")
.Replace($"[{searchText}] ", "")
.Replace($"[{searchText}]", "")
.Replace($" [{searchText}] ", " ");
}
return string.Join(' ', searchTexts);
}
}
private static bool tryParseKeywordCriteria(FilterCriteria criteria, string key, string value, Operator op)
{
switch (key)