add song filtering

This commit is contained in:
Alex
2025-09-01 18:27:30 -07:00
parent 2457eb8bd8
commit 34c461d6c4
5 changed files with 83 additions and 39 deletions
+38 -14
View File
@@ -13,6 +13,17 @@ using UAssetAPI.UnrealTypes;
namespace MercuryConverter.Data; namespace MercuryConverter.Data;
public class FilterOptions
{
public List<int> categories = [];
public List<uint> sources = [];
public override string ToString()
{
return $"categories({categories.Count()})=[{string.Join(',', categories.Select(i => i.ToString()))}];sources({sources.Count()})=[{string.Join(',', sources.Select(i => i.ToString()))}]";
}
}
public static class Database public static class Database
{ {
public static Dictionary<string, string> AudioPaths { get; } = new(); public static Dictionary<string, string> AudioPaths { get; } = new();
@@ -86,7 +97,7 @@ public static class Database
Rubi = data["Rubi"].ToString()!, Rubi = data["Rubi"].ToString()!,
Name = data["MusicMessage"].ToString()!, Name = data["MusicMessage"].ToString()!,
Artist = data["ArtistMessage"].ToString()!, Artist = data["ArtistMessage"].ToString()!,
Genre = ((IntPropertyData)data["ScoreGenre"]).Value, Category = ((IntPropertyData)data["ScoreGenre"]).Value,
Source = ((UInt32PropertyData)data["VersionNo"]).Value, Source = ((UInt32PropertyData)data["VersionNo"]).Value,
BpmMessage = data["Bpm"].ToString()!, BpmMessage = data["Bpm"].ToString()!,
PreviewTime = previewBegin, PreviewTime = previewBegin,
@@ -125,24 +136,37 @@ public static class Database
} }
} }
Console.WriteLine($"Data setup finished with {Songs.Count} songs."); Console.WriteLine($"Data setup finished with {Songs.Count} songs.");
// SEARCH TEST
var camellia = Search("camellia").ToList();
camellia.ForEach(Console.WriteLine);
} }
public static IEnumerable<Song> Search(string substr) public static IEnumerable<Song> SearchAndFilter(string substr, FilterOptions filter)
{ {
var sanitized = substr.ToLower().Trim(); /// Filter
var filtered = new List<Song>();
// by source
var sourceSongs = new List<Song>();
if (filter.sources.Count() == 0)
sourceSongs.AddRange(Songs);
else
sourceSongs.AddRange(Songs.Where(s => filter.sources.Contains(s.Source)));
// by category
if (filter.categories.Count() == 0)
filtered.AddRange(sourceSongs);
else
filtered.AddRange(sourceSongs.Where(s => filter.categories.Contains(s.Category)));
/// Search
var sanitized = string.IsNullOrEmpty(substr) ? "" : substr.ToLower().Trim();
if (sanitized == "") if (sanitized == "")
return Songs; return filtered;
return Songs.Where(s => return filtered.Where(s =>
{ {
return return
s.Artist.ToLower().Contains(sanitized) || s.Artist.ToLower().Contains(sanitized) ||
s.Name.ToLower().Contains(sanitized); s.Name.ToLower().Contains(sanitized);
}); });
} }
} }
+2 -1
View File
@@ -7,7 +7,7 @@ namespace MercuryConverter.Data;
public static class Consts public static class Consts
{ {
public static readonly IReadOnlyDictionary<int, string> CATEGORY_INDEX = new Dictionary<int, string> public static readonly IReadOnlyDictionary<int, string> CATEGORY_NAME = new Dictionary<int, string>
{ {
{ -1, "Unknown"}, { -1, "Unknown"},
{ 0, "Anime/Pop"}, { 0, "Anime/Pop"},
@@ -19,6 +19,7 @@ public static class Consts
{ 6, "HARDCORE TANO*C" }, { 6, "HARDCORE TANO*C" },
{ 7, "VTuber" }, { 7, "VTuber" },
}; };
public static readonly IReadOnlyDictionary<string, int> CATEGORY_INDEX = CATEGORY_NAME.ToDictionary(p => p.Value, p => p.Key);
public static readonly IReadOnlyDictionary<uint, string> NUM_SOURCE = new Dictionary<uint, string> public static readonly IReadOnlyDictionary<uint, string> NUM_SOURCE = new Dictionary<uint, string>
{ {
+1 -1
View File
@@ -21,7 +21,7 @@ public class Song
public required string Rubi { get; set; } public required string Rubi { get; set; }
public required string BpmMessage { get; set; } public required string BpmMessage { get; set; }
public string? Copyright { get; set; } // May have never been used? public string? Copyright { get; set; } // May have never been used?
public required int Genre { get; set; } public required int Category { get; set; }
public required string? Jacket { get; set; } public required string? Jacket { get; set; }
public required float PreviewTime { get; set; } public required float PreviewTime { get; set; }
public required float PreviewLen { get; set; } public required float PreviewLen { get; set; }
+2 -2
View File
@@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MercuryConverter.UI.Views" xmlns:local="clr-namespace:MercuryConverter.UI.Views"
d:DesignWidth="800" d:DesignHeight="400" d:DesignWidth="800" d:DesignHeight="600"
x:Class="MercuryConverter.UI.Views.Selection" x:Class="MercuryConverter.UI.Views.Selection"
xmlns:data="clr-namespace:MercuryConverter.Data" xmlns:data="clr-namespace:MercuryConverter.Data"
@@ -42,7 +42,7 @@
<!-- Song Listing Table --> <!-- Song Listing Table -->
<DockPanel> <DockPanel>
<DockPanel Margin="0 4 0 8" DockPanel.Dock="Top"> <DockPanel Margin="0 4 0 8" DockPanel.Dock="Top">
<TextBox Watermark="Search for song title or artist..." TextChanged="OnSearchTextChange"/> <TextBox Name="SearchBox" Watermark="Search for song title or artist..." TextChanged="OnSearchTextChange"/>
</DockPanel> </DockPanel>
<UserControl Background="{DynamicResource DataGridContentBackground}"> <UserControl Background="{DynamicResource DataGridContentBackground}">
<DataGrid Name="ListingTable" IsReadOnly="True" SelectionMode="Extended" ItemsSource="{x:Static data:Database.Songs}" <DataGrid Name="ListingTable" IsReadOnly="True" SelectionMode="Extended" ItemsSource="{x:Static data:Database.Songs}"
+40 -21
View File
@@ -13,6 +13,9 @@ public partial class Selection : Panel
{ {
public static ObservableRangeCollection<Song> Selections { get; } = new(); public static ObservableRangeCollection<Song> Selections { get; } = new();
private List<CheckBox> sourceCBs = new();
private List<CheckBox> categoryCBs = new();
public Selection() public Selection()
{ {
InitializeComponent(); InitializeComponent();
@@ -24,26 +27,21 @@ public partial class Selection : Panel
foreach (var (k, v) in Consts.NUM_SOURCE) foreach (var (k, v) in Consts.NUM_SOURCE)
{ {
FilterSourceContainer.Children.Add( var cb = new CheckBox { Content = v };
new CheckBox cb.IsCheckedChanged += OnFilterChange;
{ sourceCBs.Add(cb);
Name = $"FilterSourceCheckbox{k}", FilterSourceContainer.Children.Add(cb);
Content = v,
}
);
} }
foreach (var (k, v) in Consts.CATEGORY_INDEX)
foreach (var (k, v) in Consts.CATEGORY_NAME)
{ {
if (k == -1) if (k == -1)
continue; continue;
FilterCategoryContainer.Children.Add( var cb = new CheckBox { Content = v };
new CheckBox cb.IsCheckedChanged += OnFilterChange;
{ categoryCBs.Add(cb);
Name = $"FilterCategoryCheckbox{k}", FilterCategoryContainer.Children.Add(cb);
Content = v,
}
);
} }
} }
@@ -57,7 +55,7 @@ public partial class Selection : Panel
var cell = e.Cell; var cell = e.Cell;
var tb = (TextBlock)cell.Content!; var tb = (TextBlock)cell.Content!;
Console.WriteLine($"{e.PointerPressedEventArgs.Properties.IsRightButtonPressed} - {e.Cell.Content}"); // Console.WriteLine($"{e.PointerPressedEventArgs.Properties.IsRightButtonPressed} - {e.Cell.Content}");
} }
private void OnSelectionChange(object? sender, SelectionChangedEventArgs e) private void OnSelectionChange(object? sender, SelectionChangedEventArgs e)
@@ -107,14 +105,35 @@ public partial class Selection : Panel
private void OnSearchTextChange(object? _, TextChangedEventArgs args) private void OnSearchTextChange(object? _, TextChangedEventArgs args)
{ {
var src = (TextBox)args.Source!; UpdateListing();
if (string.IsNullOrEmpty(src.Text)) }
private void OnFilterChange(object? _, EventArgs __)
{
UpdateListing();
}
private void UpdateListing()
{
var filterOptions = new FilterOptions();
foreach (var cb in sourceCBs)
{ {
Dispatcher.UIThread.Post(() => ListingTable.ItemsSource = Database.Songs); if ((bool)cb.IsChecked!)
return; {
filterOptions.sources.Add(Consts.SOURCE_NUM[(string) cb.Content!]);
}
} }
var searchResults = Database.Search(src.Text.ToLower()); foreach (var cb in categoryCBs)
{
if ((bool)cb.IsChecked!)
{
filterOptions.categories.Add(Consts.CATEGORY_INDEX[(string) cb.Content!]);
}
}
var searchResults = Database.SearchAndFilter(SearchBox.Text!, filterOptions);
Dispatcher.UIThread.Post(() => ListingTable.ItemsSource = searchResults); Dispatcher.UIThread.Post(() => ListingTable.ItemsSource = searchResults);
} }
} }