public void GivenEmptyQuery_ExpectEmptyResult()
        {
            var matcher = new EnContactMatcher <TestContact>(this.Targets, this.ContactFieldsExtrator);
            var results = matcher.Find(string.Empty);

            Assert.AreEqual(0, results.Count);
        }
 public void GivenNullQuery_ExpectException()
 {
     Assert.ThrowsException <ArgumentNullException>(() =>
     {
         var matcher = new EnContactMatcher <TestContact>(this.Targets, this.ContactFieldsExtrator);
         matcher.Find(null);
     });
 }
        /// <summary>
        /// Filters the user's contact list repeatedly based on the user's input to determine the right contact and phone number to call.
        /// </summary>
        /// <param name="state">The current conversation state. This will be modified.</param>
        /// <param name="contactProvider">The provider for the user's contact list. This may be null if the contact list is not to be used.</param>
        /// <returns>The first boolean indicates whether filtering was actually performed. (In some cases, no filtering is necessary.)
        /// The second boolean indicates whether any of the contacts has a phone number whose type matches the requested type.</returns>
        public async Task <(bool, bool)> FilterAsync(PhoneSkillState state, IContactProvider contactProvider)
        {
            var isFiltered = false;

            var searchQuery = string.Empty;

            if (state.LuisResult.Entities.contactName != null)
            {
                searchQuery = string.Join(" ", state.LuisResult.Entities.contactName);
            }

            if (searchQuery.Any() && !(searchQuery == state.ContactResult.SearchQuery && state.ContactResult.Matches.Any()))
            {
                IList <ContactCandidate> contacts;
                if (state.ContactResult.Matches.Any())
                {
                    contacts = state.ContactResult.Matches;
                }
                else if (contactProvider != null)
                {
                    contacts = await contactProvider.GetContactsAsync();
                }
                else
                {
                    contacts = new List <ContactCandidate>();
                }

                if (contacts.Any())
                {
                    // TODO Adjust max number of returned contacts?
                    var matcher = new EnContactMatcher <ContactCandidate>(contacts, ExtractContactFields);
                    var matches = matcher.FindByName(searchQuery);

                    if (!state.ContactResult.Matches.Any() || matches.Any())
                    {
                        isFiltered = isFiltered || matches.Count != state.ContactResult.Matches.Count;
                        state.ContactResult.SearchQuery = searchQuery;
                        state.ContactResult.Matches     = matches;
                    }
                }
            }

            SetRequestedPhoneNumberType(state);
            var hasPhoneNumberOfRequestedType = false;

            (isFiltered, hasPhoneNumberOfRequestedType) = FilterPhoneNumbersByType(state, isFiltered);

            SetPhoneNumber(state);

            return(isFiltered, hasPhoneNumberOfRequestedType);
        }
        public void GivenExactMatch_ExpectPositiveMatch()
        {
            var matcher = new EnContactMatcher <TestContact>(this.Targets, this.ContactFieldsExtrator);
            var results = matcher.Find("Andrew Smith");

            Assert.AreEqual(1, results.Count);
            var expected = new TestContact()
            {
                FirstName = "Andrew",
                LastName  = "Smith",
                Id        = "1234567"
            };

            Assert.AreEqual(expected, results[0]);
        }
        public void GivenSimilarPhoneticWeight_ExpectPositiveMatch()
        {
            var matcher = new EnContactMatcher <TestContact>(this.Targets, this.ContactFieldsExtrator);
            var results = matcher.Find("andru");

            Assert.AreEqual(2, results.Count);
            var expected = new TestContact()
            {
                FirstName = "Andrew",
                LastName  = string.Empty
            };

            Assert.IsTrue(results.Contains(expected));
            expected = new TestContact()
            {
                FirstName = "Andrew",
                LastName  = "Smith",
                Id        = "1234567"
            };
            Assert.IsTrue(results.Contains(expected));
        }
        public void GivenDuplicateNames_ExpectPositiveMatch()
        {
            var matcher = new EnContactMatcher <TestContact>(this.Targets, this.ContactFieldsExtrator);
            var results = matcher.Find("john");

            Assert.AreEqual(2, results.Count);
            var expected = new TestContact()
            {
                FirstName = "John",
                LastName  = "B",
                Id        = "7654321"
            };

            Assert.IsTrue(results.Contains(expected));
            expected = new TestContact()
            {
                FirstName = "John",
                LastName  = "C",
                Id        = "2222222"
            };
            Assert.IsTrue(results.Contains(expected));
        }
        /// <summary>
        /// Usage ".\PhoneticMatcherPerfTests contact|place timeoutMilliseconds [accuracy]"
        /// </summary>
        /// <example>
        /// ".\PhoneticMatcherPerfTests contact 20000" Runs queries for 20 seconds for user to profiler performance results.
        /// </example>
        /// <param name="args">Command line arguments</param>
        private static void Main(string[] args)
        {
            string type = args[0];
            int    timeoutMilliseconds;
            double maxTimeout   = TimeSpan.FromDays(7).TotalMilliseconds;
            string errorTimeout = $"second argument is the time during the profiling will last. It must be a valid integer between 1 and {maxTimeout} (one week)";

            if (!int.TryParse(args[1], out timeoutMilliseconds))
            {
                throw new ArgumentException(errorTimeout);
            }

            if (timeoutMilliseconds < 1 || timeoutMilliseconds > maxTimeout)
            {
                throw new ArgumentOutOfRangeException(errorTimeout + $" - current value : {timeoutMilliseconds}");
            }

            bool isAccuracyTest = false;

            if (args.Length > 2)
            {
                isAccuracyTest = string.Compare(args[2], "accuracy", true) == 0;
            }

            Console.WriteLine("Starting tests...");
            var sw = new Stopwatch();

            sw.Start();
            switch (type.ToLowerInvariant())
            {
            case Contact:
            {
                TestElement <ContactFields>[] contacts = JsonConvert.DeserializeObject <TestElement <ContactFields>[]>(File.ReadAllText(@".\contacts.json"));
                Console.WriteLine($"Took {sw.Elapsed} to deserialize contact fields.");
                sw.Restart();
                var contactFields = contacts.Select(c => c.Element).ToArray();
                var matcher       = new EnContactMatcher <ContactFields>(contactFields, c => c, new ContactMatcherConfig(maxReturns: MaxReturns));
                var tester        = new FuzzyMatcherPerfTester <ContactFields>(matcher, contacts);
                Console.WriteLine($"Took {sw.Elapsed} to instantiate Contact Matcher with {contactFields.Length} contacts.");
                tester.Run(TimeSpan.FromMilliseconds(timeoutMilliseconds), isAccuracyTest);
                break;
            }

            case Place:
            {
                TestElement <PlaceFields>[] places = JsonConvert.DeserializeObject <TestElement <PlaceFields>[]>(File.ReadAllText(@".\places.json"));
                Console.WriteLine($"Took {sw.Elapsed} to deserialize place fields.");
                sw.Restart();
                var placeFields = places.Select(c => c.Element).ToArray();
                var matcher     = new EnPlaceMatcher <PlaceFields>(placeFields, c => c, new PlaceMatcherConfig(maxReturns: MaxReturns));
                var tester      = new FuzzyMatcherPerfTester <PlaceFields>(matcher, places);
                Console.WriteLine($"Took {sw.Elapsed} to instantiate Place Matcher with {placeFields.Length} places.");

                tester.Run(TimeSpan.FromMilliseconds(timeoutMilliseconds), isAccuracyTest);
                break;
            }

            default:
                throw new ArgumentException($"Type must be 'place' or 'contact'. Current value: {type}");
            }
        }