public TrackMapping MapReleaseTracks(List <LocalTrack> localTracks, List <Track> mbTracks) { var distances = new Distance[localTracks.Count, mbTracks.Count]; var costs = new double[localTracks.Count, mbTracks.Count]; for (int col = 0; col < mbTracks.Count; col++) { var totalTrackNumber = GetTotalTrackNumber(mbTracks[col], mbTracks); for (int row = 0; row < localTracks.Count; row++) { distances[row, col] = TrackDistance(localTracks[row], mbTracks[col], totalTrackNumber, false); costs[row, col] = distances[row, col].NormalizedDistance(); } } var m = new Munkres(costs); m.Run(); var result = new TrackMapping(); foreach (var pair in m.Solution) { result.Mapping.Add(localTracks[pair.Item1], Tuple.Create(mbTracks[pair.Item2], distances[pair.Item1, pair.Item2])); _logger.Trace("Mapped {0} to {1}, dist: {2}", localTracks[pair.Item1], mbTracks[pair.Item2], costs[pair.Item1, pair.Item2]); } result.LocalExtra = localTracks.Except(result.Mapping.Keys).ToList(); _logger.Trace($"Unmapped files:\n{string.Join("\n", result.LocalExtra)}"); result.MBExtra = mbTracks.Except(result.Mapping.Values.Select(x => x.Item1)).ToList(); _logger.Trace($"Missing tracks:\n{string.Join("\n", result.MBExtra)}"); return(result); }
private TrackMapping GivenMapping(List <LocalTrack> local, List <Track> remote) { var mapping = new TrackMapping(); var distances = local.Zip(remote, (l, r) => Tuple.Create(r, Subject.TrackDistance(l, r, Subject.GetTotalTrackNumber(r, remote)))); mapping.Mapping = local.Zip(distances, (l, r) => new { l, r }).ToDictionary(x => x.l, x => x.r); mapping.LocalExtra = local.Except(mapping.Mapping.Keys).ToList(); mapping.MBExtra = remote.Except(mapping.Mapping.Values.Select(x => x.Item1)).ToList(); return(mapping); }
public bool Equals(FilterResult other) { if (ReferenceEquals(null, other)) { return(false); } if (ReferenceEquals(this, other)) { return(true); } return(Id.Equals(other.Id) && Uid.Equals(other.Uid) && string.Equals(Name, other.Name) && string.Equals(Description, other.Description) && StartUtc.Equals(other.StartUtc) && EndUtc.Equals(other.EndUtc) && OnMachineDesignId == other.OnMachineDesignId && OnMachineDesignName == other.OnMachineDesignName && AssetIDs.ScrambledEquals(other.AssetIDs) && VibeStateOn == other.VibeStateOn && CompactorDataOnly.Equals(other.CompactorDataOnly) && ElevationType == other.ElevationType && PolygonLL.ScrambledEquals(other.PolygonLL) && PolygonGrid.ScrambledEquals(other.PolygonGrid) && ForwardDirection == other.ForwardDirection && (AlignmentFile == null ? other.AlignmentFile == null : AlignmentFile.Equals(other.AlignmentFile)) && StartStation.Equals(other.StartStation) && EndStation.Equals(other.EndStation) && LeftOffset.Equals(other.LeftOffset) && RightOffset.Equals(other.RightOffset) && LayerType.Equals(other.LayerType) && (LayerDesignOrAlignmentFile == null ? other.LayerDesignOrAlignmentFile == null : LayerDesignOrAlignmentFile.Equals(other.LayerDesignOrAlignmentFile)) && BenchElevation.Equals(other.BenchElevation) && LayerNumber == other.LayerNumber && LayerThickness.Equals(other.LayerThickness) && ContributingMachines.ScrambledEquals(other.ContributingMachines) && SurveyedSurfaceExclusionList.ScrambledEquals(other.SurveyedSurfaceExclusionList) && ExcludedSurveyedSurfaceUids.ScrambledEquals(other.ExcludedSurveyedSurfaceUids) && ReturnEarliest.Equals(other.ReturnEarliest) && GpsAccuracy.Equals(other.GpsAccuracy) && GpsAccuracyIsInclusive.Equals(other.GpsAccuracyIsInclusive) && BladeOnGround.Equals(other.BladeOnGround) && TrackMapping.Equals(other.TrackMapping) && WheelTracking.Equals(other.WheelTracking) && (DesignFile == null ? other.DesignFile == null : DesignFile.Equals(other.DesignFile)) && AutomaticsType == other.AutomaticsType && TemperatureRangeMin.Equals(other.TemperatureRangeMin) && TemperatureRangeMax.Equals(other.TemperatureRangeMax) && PassCountRangeMin.Equals(other.PassCountRangeMin) && PassCountRangeMax.Equals(other.PassCountRangeMax)); }
public Distance AlbumReleaseDistance(List <LocalTrack> localTracks, AlbumRelease release, TrackMapping mapping) { var dist = new Distance(); if (!VariousArtistIds.Contains(release.Album.Value.ArtistMetadata.Value.ForeignArtistId)) { var artist = MostCommon(localTracks.Select(x => x.FileTrackInfo.ArtistTitle)) ?? ""; dist.AddString("artist", artist, release.Album.Value.ArtistMetadata.Value.Name); _logger.Trace("artist: {0} vs {1}; {2}", artist, release.Album.Value.ArtistMetadata.Value.Name, dist.NormalizedDistance()); } var title = MostCommon(localTracks.Select(x => x.FileTrackInfo.AlbumTitle)) ?? ""; // Use the album title since the differences in release titles can cause confusion and // aren't always correct in the tags dist.AddString("album", title, release.Album.Value.Title); _logger.Trace("album: {0} vs {1}; {2}", title, release.Title, dist.NormalizedDistance()); // Number of discs, either as tagged or the max disc number seen var discCount = MostCommon(localTracks.Select(x => x.FileTrackInfo.DiscCount)); discCount = discCount != 0 ? discCount : localTracks.Max(x => x.FileTrackInfo.DiscNumber); if (discCount > 0) { dist.AddNumber("media_count", discCount, release.Media.Count); _logger.Trace("media_count: {0} vs {1}; {2}", discCount, release.Media.Count, dist.NormalizedDistance()); } // Media format if (release.Media.Select(x => x.Format).Contains("Unknown")) { dist.Add("media_format", 1.0); } // Year var localYear = MostCommon(localTracks.Select(x => x.FileTrackInfo.Year)); if (localYear > 0 && (release.Album.Value.ReleaseDate.HasValue || release.ReleaseDate.HasValue)) { var albumYear = release.Album.Value.ReleaseDate?.Year ?? 0; var releaseYear = release.ReleaseDate?.Year ?? 0; if (localYear == albumYear || localYear == releaseYear) { dist.Add("year", 0.0); } else { var remoteYear = albumYear > 0 ? albumYear : releaseYear; var diff = Math.Abs(localYear - remoteYear); var diff_max = Math.Abs(DateTime.Now.Year - remoteYear); dist.AddRatio("year", diff, diff_max); } _logger.Trace($"year: {localYear} vs {release.Album.Value.ReleaseDate?.Year} or {release.ReleaseDate?.Year}; {dist.NormalizedDistance()}"); } // If we parsed a country from the files use that, otherwise use our preference var country = MostCommon(localTracks.Select(x => x.FileTrackInfo.Country)); if (release.Country.Count > 0) { if (country != null) { dist.AddEquality("country", country.Name, release.Country); _logger.Trace("country: {0} vs {1}; {2}", country.Name, string.Join(", ", release.Country), dist.NormalizedDistance()); } else if (preferredCountries.Count > 0) { dist.AddPriority("country", release.Country, preferredCountries.Select(x => x.Name).ToList()); _logger.Trace("country priority: {0} vs {1}; {2}", string.Join(", ", preferredCountries.Select(x => x.Name)), string.Join(", ", release.Country), dist.NormalizedDistance()); } } else { // full penalty if MusicBrainz release is missing a country dist.Add("country", 1.0); } var label = MostCommon(localTracks.Select(x => x.FileTrackInfo.Label)); if (label.IsNotNullOrWhiteSpace()) { dist.AddEquality("label", label, release.Label); _logger.Trace("label: {0} vs {1}; {2}", label, string.Join(", ", release.Label), dist.NormalizedDistance()); } var disambig = MostCommon(localTracks.Select(x => x.FileTrackInfo.Disambiguation)); if (disambig.IsNotNullOrWhiteSpace()) { dist.AddString("album_disambiguation", disambig, release.Disambiguation); _logger.Trace("album_disambiguation: {0} vs {1}; {2}", disambig, release.Disambiguation, dist.NormalizedDistance()); } var mbAlbumId = MostCommon(localTracks.Select(x => x.FileTrackInfo.ReleaseMBId)); if (mbAlbumId.IsNotNullOrWhiteSpace()) { dist.AddBool("album_id", mbAlbumId != release.ForeignReleaseId && !release.OldForeignReleaseIds.Contains(mbAlbumId)); _logger.Trace("album_id: {0} vs {1} or {2}; {3}", mbAlbumId, release.ForeignReleaseId, string.Join(", ", release.OldForeignReleaseIds), dist.NormalizedDistance()); } // tracks foreach (var pair in mapping.Mapping) { dist.Add("tracks", pair.Value.Item2.NormalizedDistance()); } _logger.Trace("after trackMapping: {0}", dist.NormalizedDistance()); // missing tracks foreach (var track in mapping.MBExtra.Take(localTracks.Count)) { dist.Add("missing_tracks", 1.0); } _logger.Trace("after missing tracks: {0}", dist.NormalizedDistance()); // unmatched tracks foreach (var track in mapping.LocalExtra.Take(localTracks.Count)) { dist.Add("unmatched_tracks", 1.0); } _logger.Trace("after unmatched tracks: {0}", dist.NormalizedDistance()); return(dist); }