From 09fcd384ab308799f97ed6809161dc9c93b18fe5 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sat, 12 Mar 2022 21:09:51 -0800 Subject: [PATCH] Make fully and partially matching IDs more apparent Add write offset as read-only field --- CHANGELIST.md | 2 + MPF.Library/InfoTool.cs | 74 +++++++++++++--------- MPF.Test/RedumpLib/SubmissionInfoTests.cs | 3 +- MPF/ViewModels/DiscInformationViewModel.cs | 14 +++- MPF/ViewModels/MainViewModel.cs | 3 +- MPF/Windows/DiscInformationWindow.xaml | 4 +- RedumpLib/Data/SubmissionInfo.cs | 12 +++- 7 files changed, 74 insertions(+), 38 deletions(-) diff --git a/CHANGELIST.md b/CHANGELIST.md index c839151b..8eb3bb01 100644 --- a/CHANGELIST.md +++ b/CHANGELIST.md @@ -26,6 +26,8 @@ - Return faster on empty protection sets - Remove redundant check around volume label - Fix tabs in Games and Videos boxes +- Make fully and partially matching IDs more apparent +- Add write offset as read-only field ### 2.3 (2022-02-05) - Start overhauling Redump information pulling, again diff --git a/MPF.Library/InfoTool.cs b/MPF.Library/InfoTool.cs index f6eb8137..4ce4142c 100644 --- a/MPF.Library/InfoTool.cs +++ b/MPF.Library/InfoTool.cs @@ -644,7 +644,7 @@ namespace MPF.Library info.SizeAndChecksums.Layerbreak3), 1); AddIfExists(output, Template.CategoryField, info.CommonDiscInfo.Category.LongName(), 1); - AddIfExists(output, Template.MatchingIDsField, info.MatchedIDs, 1); + AddIfExists(output, Template.MatchingIDsField, info.PartiallyMatchedIDs, 1); AddIfExists(output, Template.RegionField, info.CommonDiscInfo.Region.LongName() ?? "SPACE! (CHANGE THIS)", 1); AddIfExists(output, Template.LanguagesField, (info.CommonDiscInfo.Languages ?? new Language?[] { null }).Select(l => l.LongName() ?? "SILENCE! (CHANGE THIS)").ToArray(), 1); AddIfExists(output, Template.PlaystationLanguageSelectionViaField, (info.CommonDiscInfo.LanguageSelection ?? new LanguageSelection?[] { }).Select(l => l.LongName()).ToArray(), 1); @@ -1603,7 +1603,7 @@ namespace MPF.Library { // Set the current dumper based on username info.DumpersAndStatus.Dumpers = new string[] { options.RedumpUsername }; - info.MatchedIDs = new List(); + info.PartiallyMatchedIDs = new List(); using (RedumpWebClient wc = new RedumpWebClient()) { @@ -1620,38 +1620,59 @@ namespace MPF.Library return; } - // Loop through all of the hashdata to find matching IDs + // Setup the full-track checks bool allFound = true; + List fullyMatchedIDs = null; + + // Loop through all of the hashdata to find matching IDs resultProgress?.Report(Result.Success("Finding disc matches on Redump...")); string[] splitData = info.TracksAndWriteOffsets.ClrMameProData.Split('\n'); foreach (string hashData in splitData) { - allFound &= ValidateSingleTrack(wc, info, hashData, resultProgress); + (bool singleFound, List foundIds) = ValidateSingleTrack(wc, info, hashData, resultProgress); + + // Ensure that all tracks are found + allFound &= singleFound; + + // If we found a track, only keep track of distinct found tracks + if (singleFound && foundIds != null) + { + if (fullyMatchedIDs == null) + fullyMatchedIDs = foundIds; + else + fullyMatchedIDs = fullyMatchedIDs.Intersect(foundIds).ToList(); + } } - resultProgress?.Report(Result.Success("Match finding complete! " + (info.MatchedIDs.Count > 0 - ? "Matched IDs: " + string.Join(",", info.MatchedIDs) + // Make sure we only have unique IDs + info.PartiallyMatchedIDs = info.PartiallyMatchedIDs + .Distinct() + .OrderBy(id => id) + .ToList(); + + resultProgress?.Report(Result.Success("Match finding complete! " + (fullyMatchedIDs.Count > 0 + ? "Fully Matched IDs: " + string.Join(",", fullyMatchedIDs) : "No matches found"))); // Exit early if one failed or there are no matched IDs - if (!allFound || info.MatchedIDs.Count == 0) + if (!allFound || fullyMatchedIDs.Count == 0) return; // Find the first matched ID where the track count matches, we can grab a bunch of info from it - int totalMatchedIDsCount = info.MatchedIDs.Count; + int totalMatchedIDsCount = fullyMatchedIDs.Count; for (int i = 0; i < totalMatchedIDsCount; i++) { // Skip if the track count doesn't match - if (!ValidateTrackCount(wc, info.MatchedIDs[i], splitData.Length)) + if (!ValidateTrackCount(wc, fullyMatchedIDs[i], splitData.Length)) continue; // Fill in the fields from the existing ID - resultProgress?.Report(Result.Success($"Filling fields from existing ID {info.MatchedIDs[i]}...")); - FillFromId(wc, info, info.MatchedIDs[0]); + resultProgress?.Report(Result.Success($"Filling fields from existing ID {fullyMatchedIDs[i]}...")); + FillFromId(wc, info, fullyMatchedIDs[i]); resultProgress?.Report(Result.Success("Information filling complete!")); - // Set the matched IDs to just the current - info.MatchedIDs = new List { info.MatchedIDs[i] }; + // Set the fully matched ID to the current + info.FullyMatchedID = fullyMatchedIDs[i]; break; } } @@ -1736,14 +1757,14 @@ namespace MPF.Library /// Existing SubmissionInfo object to fill /// DAT-formatted hash data to parse out /// Optional result progress callback - /// True if the track was found, false otherwise - private static bool ValidateSingleTrack(RedumpWebClient wc, SubmissionInfo info, string hashData, IProgress resultProgress = null) + /// True if the track was found, false otherwise; List of found values, if possible + private static (bool, List) ValidateSingleTrack(RedumpWebClient wc, SubmissionInfo info, string hashData, IProgress resultProgress = null) { // If the line isn't parseable, we can't validate if (!GetISOHashValues(hashData, out long _, out string _, out string _, out string sha1)) { resultProgress?.Report(Result.Failure("Line could not be parsed for hash data")); - return false; + return (false, null); } // Get all matching IDs for the track @@ -1753,25 +1774,20 @@ namespace MPF.Library if (newIds == null) { resultProgress?.Report(Result.Failure("There was an unknown error retrieving information from Redump")); - return false; + return (false, null); } - // If no IDs match any track, then we don't match a disc at all + // If no IDs match any track, just return if (!newIds.Any()) - { - info.MatchedIDs = new List(); - return false; - } + return (false, null); - // If we have multiple tracks, only take IDs that are in common - if (info.MatchedIDs.Any()) - info.MatchedIDs = info.MatchedIDs.Intersect(newIds).ToList(); - - // If we're on the first track, all IDs are added + // Join the list of found IDs to the existing list, if possible + if (info.PartiallyMatchedIDs.Any()) + info.PartiallyMatchedIDs.AddRange(newIds); else - info.MatchedIDs = newIds; + info.PartiallyMatchedIDs = newIds; - return true; + return (true, newIds); } /// diff --git a/MPF.Test/RedumpLib/SubmissionInfoTests.cs b/MPF.Test/RedumpLib/SubmissionInfoTests.cs index 8b2485b4..8d556f6e 100644 --- a/MPF.Test/RedumpLib/SubmissionInfoTests.cs +++ b/MPF.Test/RedumpLib/SubmissionInfoTests.cs @@ -42,7 +42,8 @@ namespace MPF.Test.RedumpLib var submissionInfo = new SubmissionInfo() { SchemaVersion = 1, - MatchedIDs = new List { 0, 1, 2, 3 }, + FullyMatchedID = 3, + PartiallyMatchedIDs = new List { 0, 1, 2, 3 }, Added = DateTime.UtcNow, LastModified = DateTime.UtcNow, diff --git a/MPF/ViewModels/DiscInformationViewModel.cs b/MPF/ViewModels/DiscInformationViewModel.cs index 2e21f799..1634bbab 100644 --- a/MPF/ViewModels/DiscInformationViewModel.cs +++ b/MPF/ViewModels/DiscInformationViewModel.cs @@ -266,14 +266,22 @@ namespace MPF.GUI.ViewModels /// private void HideReadOnlyFields() { - if (SubmissionInfo?.MatchedIDs == null) - Parent.MatchedIDs.Visibility = Visibility.Collapsed; + if (SubmissionInfo?.FullyMatchedID == null) + Parent.FullyMatchedID.Visibility = Visibility.Collapsed; else - Parent.MatchedIDs.Text = string.Join(", ", SubmissionInfo.MatchedIDs); + Parent.FullyMatchedID.Text = SubmissionInfo.FullyMatchedID.ToString(); + if (SubmissionInfo?.PartiallyMatchedIDs == null) + Parent.PartiallyMatchedIDs.Visibility = Visibility.Collapsed; + else + Parent.PartiallyMatchedIDs.Text = string.Join(", ", SubmissionInfo.PartiallyMatchedIDs); if (SubmissionInfo?.CopyProtection?.AntiModchip == null) Parent.AntiModchip.Visibility = Visibility.Collapsed; else Parent.AntiModchip.Text = SubmissionInfo.CopyProtection.AntiModchip.LongName(); + if (SubmissionInfo?.TracksAndWriteOffsets?.OtherWriteOffsets == null) + Parent.DiscOffset.Visibility = Visibility.Collapsed; + else + Parent.DiscOffset.Text = SubmissionInfo.TracksAndWriteOffsets.OtherWriteOffsets; if (SubmissionInfo?.CommonDiscInfo?.CommentsSpecialFields.Keys.Contains(SiteCode.DMIHash) != true) Parent.DMIHash.Visibility = Visibility.Collapsed; if (string.IsNullOrWhiteSpace(SubmissionInfo?.CommonDiscInfo?.ErrorsCount)) diff --git a/MPF/ViewModels/MainViewModel.cs b/MPF/ViewModels/MainViewModel.cs index 4bdf1072..597418e9 100644 --- a/MPF/ViewModels/MainViewModel.cs +++ b/MPF/ViewModels/MainViewModel.cs @@ -282,7 +282,8 @@ namespace MPF.GUI.ViewModels var submissionInfo = new SubmissionInfo() { SchemaVersion = 1, - MatchedIDs = new List { 0, 1, 2, 3 }, + FullyMatchedID = 3, + PartiallyMatchedIDs = new List { 0, 1, 2, 3 }, Added = DateTime.UtcNow, LastModified = DateTime.UtcNow, diff --git a/MPF/Windows/DiscInformationWindow.xaml b/MPF/Windows/DiscInformationWindow.xaml index 47c120b6..81fe11d1 100644 --- a/MPF/Windows/DiscInformationWindow.xaml +++ b/MPF/Windows/DiscInformationWindow.xaml @@ -335,8 +335,10 @@ - + + + - /// List of matched Redump IDs + /// Fully matched Redump ID /// [JsonIgnore] - public List MatchedIDs { get; set; } + public int? FullyMatchedID { get; set; } + + /// + /// List of partially matched Redump IDs + /// + [JsonIgnore] + public List PartiallyMatchedIDs { get; set; } /// /// DateTime of when the disc was added @@ -67,7 +73,7 @@ namespace RedumpLib.Data return new SubmissionInfo { SchemaVersion = this.SchemaVersion, - MatchedIDs = this.MatchedIDs, + PartiallyMatchedIDs = this.PartiallyMatchedIDs, Added = this.Added, LastModified = this.LastModified, CommonDiscInfo = this.CommonDiscInfo?.Clone() as CommonDiscInfoSection,