mirror of
https://github.com/muskit/MercuryConverter.git
synced 2026-06-02 20:24:26 -07:00
add song filtering
This commit is contained in:
+38
-14
@@ -13,6 +13,17 @@ using UAssetAPI.UnrealTypes;
|
||||
|
||||
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 Dictionary<string, string> AudioPaths { get; } = new();
|
||||
@@ -86,7 +97,7 @@ public static class Database
|
||||
Rubi = data["Rubi"].ToString()!,
|
||||
Name = data["MusicMessage"].ToString()!,
|
||||
Artist = data["ArtistMessage"].ToString()!,
|
||||
Genre = ((IntPropertyData)data["ScoreGenre"]).Value,
|
||||
Category = ((IntPropertyData)data["ScoreGenre"]).Value,
|
||||
Source = ((UInt32PropertyData)data["VersionNo"]).Value,
|
||||
BpmMessage = data["Bpm"].ToString()!,
|
||||
PreviewTime = previewBegin,
|
||||
@@ -125,24 +136,37 @@ public static class Database
|
||||
}
|
||||
}
|
||||
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 == "")
|
||||
return Songs;
|
||||
return filtered;
|
||||
|
||||
return Songs.Where(s =>
|
||||
{
|
||||
return
|
||||
s.Artist.ToLower().Contains(sanitized) ||
|
||||
s.Name.ToLower().Contains(sanitized);
|
||||
});
|
||||
return filtered.Where(s =>
|
||||
{
|
||||
return
|
||||
s.Artist.ToLower().Contains(sanitized) ||
|
||||
s.Name.ToLower().Contains(sanitized);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace MercuryConverter.Data;
|
||||
|
||||
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"},
|
||||
{ 0, "Anime/Pop"},
|
||||
@@ -19,6 +19,7 @@ public static class Consts
|
||||
{ 6, "HARDCORE TANO*C" },
|
||||
{ 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>
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ public class Song
|
||||
public required string Rubi { get; set; }
|
||||
public required string BpmMessage { get; set; }
|
||||
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 float PreviewTime { get; set; }
|
||||
public required float PreviewLen { get; set; }
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
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"
|
||||
xmlns:data="clr-namespace:MercuryConverter.Data"
|
||||
@@ -42,7 +42,7 @@
|
||||
<!-- Song Listing Table -->
|
||||
<DockPanel>
|
||||
<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>
|
||||
<UserControl Background="{DynamicResource DataGridContentBackground}">
|
||||
<DataGrid Name="ListingTable" IsReadOnly="True" SelectionMode="Extended" ItemsSource="{x:Static data:Database.Songs}"
|
||||
|
||||
@@ -13,6 +13,9 @@ public partial class Selection : Panel
|
||||
{
|
||||
public static ObservableRangeCollection<Song> Selections { get; } = new();
|
||||
|
||||
private List<CheckBox> sourceCBs = new();
|
||||
private List<CheckBox> categoryCBs = new();
|
||||
|
||||
public Selection()
|
||||
{
|
||||
InitializeComponent();
|
||||
@@ -24,26 +27,21 @@ public partial class Selection : Panel
|
||||
|
||||
foreach (var (k, v) in Consts.NUM_SOURCE)
|
||||
{
|
||||
FilterSourceContainer.Children.Add(
|
||||
new CheckBox
|
||||
{
|
||||
Name = $"FilterSourceCheckbox{k}",
|
||||
Content = v,
|
||||
}
|
||||
);
|
||||
var cb = new CheckBox { Content = v };
|
||||
cb.IsCheckedChanged += OnFilterChange;
|
||||
sourceCBs.Add(cb);
|
||||
FilterSourceContainer.Children.Add(cb);
|
||||
}
|
||||
foreach (var (k, v) in Consts.CATEGORY_INDEX)
|
||||
|
||||
foreach (var (k, v) in Consts.CATEGORY_NAME)
|
||||
{
|
||||
if (k == -1)
|
||||
continue;
|
||||
|
||||
FilterCategoryContainer.Children.Add(
|
||||
new CheckBox
|
||||
{
|
||||
Name = $"FilterCategoryCheckbox{k}",
|
||||
Content = v,
|
||||
}
|
||||
);
|
||||
var cb = new CheckBox { Content = v };
|
||||
cb.IsCheckedChanged += OnFilterChange;
|
||||
categoryCBs.Add(cb);
|
||||
FilterCategoryContainer.Children.Add(cb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +55,7 @@ public partial class Selection : Panel
|
||||
var cell = e.Cell;
|
||||
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)
|
||||
@@ -107,14 +105,35 @@ public partial class Selection : Panel
|
||||
|
||||
private void OnSearchTextChange(object? _, TextChangedEventArgs args)
|
||||
{
|
||||
var src = (TextBox)args.Source!;
|
||||
if (string.IsNullOrEmpty(src.Text))
|
||||
UpdateListing();
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
if ((bool)cb.IsChecked!)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user