public void CustomQueryConfigurationParametersCanBeSuccessfullySetTest()
        {
            var queryConfiguration = new CustomQueryConfiguration { ThresholdVotes = 7, MaximumNumberOfTracksToReturnAsResult = 10 };

            Assert.AreEqual(7, queryConfiguration.ThresholdVotes);
            Assert.AreEqual(10, queryConfiguration.MaximumNumberOfTracksToReturnAsResult);
        }
        public void CustomQueryConfigurationInheritsDefaultValuesTest()
        {
            var queryConfiguration = new CustomQueryConfiguration();
            var defaultConfiguration = new DefaultQueryConfiguration();

            Assert.AreEqual(defaultConfiguration.ThresholdVotes, queryConfiguration.ThresholdVotes);
            Assert.AreEqual(defaultConfiguration.MaximumNumberOfTracksToReturnAsResult, queryConfiguration.MaximumNumberOfTracksToReturnAsResult);
        }
        /// <summary>
        ///   Find duplicates between existing tracks in the database
        /// </summary>
        /// <param name = "callback">Callback invoked at each processed track</param>
        /// <returns>Sets of duplicates</returns>
        public HashSet<TrackData>[] FindDuplicates(Action<TrackData, int, int> callback)
        {
            var tracks = modelService.ReadAllTracks();
            var duplicates = new List<HashSet<TrackData>>();
            int total = tracks.Count, current = 0;
            var queryConfiguration = new CustomQueryConfiguration { ThresholdVotes = ThresholdVotes, MaximumNumberOfTracksToReturnAsResult = int.MaxValue };
            foreach (var track in tracks)
            {
                var trackDuplicates = new HashSet<TrackData>();

                var hashes = modelService.ReadHashDataByTrack(track.TrackReference);
                var result = queryFingerprintService.Query(modelService, hashes, queryConfiguration);

                if (result.IsSuccessful)
                {
                    foreach (var resultEntry in result.ResultEntries)
                    {
                        if (track.Equals(resultEntry.Track))
                        {
                            continue;
                        }

                        if (MinimumHammingSimilarity > resultEntry.Similarity)
                        {
                            continue;
                        }

                        trackDuplicates.Add(resultEntry.Track);
                    }

                    if (trackDuplicates.Any())
                    {
                        HashSet<TrackData> duplicatePair = new HashSet<TrackData>(trackDuplicates) { track };
                        duplicates.Add(duplicatePair);
                    }
                }

                if (callback != null)
                {
                    callback.Invoke(track, total, ++current);
                }
            }

            for (int i = 0; i < duplicates.Count - 1; i++)
            {
                HashSet<TrackData> set = duplicates[i];
                for (int j = i + 1; j < duplicates.Count; j++)
                {
                    IEnumerable<TrackData> result = set.Intersect(duplicates[j]);
                    if (result.Any())
                    {
                        foreach (var track in duplicates[j])
                        {
                            // collapse all duplicates in one set
                            set.Add(track);
                        }

                        duplicates.RemoveAt(j); /*Remove the duplicate set*/
                        j--;
                    }
                }
            }

            return duplicates.ToArray();
        }
 public void InvalidMaximumNumberOfTracksToReturnIsSetOnQueryConfigurationInstanceTest()
 {
     var queryConfig = new CustomQueryConfiguration { MaximumNumberOfTracksToReturnAsResult = 0 };
     Assert.Fail();
 }
 public void InvalidThresholdVotesIsSetOnQueryConfigurationInstanceTest()
 {
     var queryConfig = new CustomQueryConfiguration { ThresholdVotes = -1 };
     Assert.Fail();
 }