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;
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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}"
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user