public void DataTypes_RangeResolve_daterange_year()
        {
            var candidates  = new[] { "XXXX-05-29" };
            var constraints = new[] { "2018" };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2018-05-29"));
            Assert.AreEqual(1, r.Count);
        }
        public void DataTypes_RangeResolve_daterange_definite_constrainst_as_timex()
        {
            var candidates  = new[] { "2017-09-28" };
            var constraints = new[] { "(2017-09-27,2017-09-29,P2D)" };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-28"));
            Assert.AreEqual(1, r.Count);
        }
        public void DataTypes_RangeResolve_daterange_multiple_overlapping_constraints()
        {
            var candidates  = new[] { "XXXX-WXX-3" };
            var constraints = new[] { "(2017-09-03,2017-09-07,P4D)", "(2017-09-01,2017-09-08,P7D)", "(2017-09-01,2017-09-16,P15D)" };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-06"));
            Assert.AreEqual(1, r.Count);
        }
예제 #4
0
        public void DataTypes_RangeResolve_duration_no_constraints()
        {
            var constraints = new List <string>
            {
                // empty
            };

            var result = TimexRangeResolver.Evaluate(new[] { "PT5M" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsFalse(r.Any());
        }
예제 #5
0
        public void DataTypes_RangeResolve_carry_through_time_definite_constrainst_expressed_as_timex()
        {
            var constraints = new List <string> {
                "(2017-09-27,2017-09-29,P2D)"
            };

            var result = TimexRangeResolver.Evaluate(new[] { "2017-09-28T18:30:01" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-28T18:30:01"));
            Assert.AreEqual(1, r.Count);
        }
예제 #6
0
        public void DataTypes_RangeResolve_dateranges_non_overlapping_constraint()
        {
            var candidates  = new[] { "XXXX-WXX-7TEV" };
            var constraints = new[]
            {
                "(2018-06-04,2018-06-11,P7D)",  // e.g. this week
                "(2018-06-11,2018-06-18,P7D)",  // e.g. next week
                TimexCreator.Morning,
            };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            Assert.IsFalse(result.Any());
        }
예제 #7
0
        public void DataTypes_RangeResolve_daterange_definite()
        {
            var candidates  = new[] { "2017-09-28" };
            var constraints = new[] { (new TimexProperty {
                    Year = 2017, Month = 9, DayOfMonth = 27, Days = 2
                }).TimexValue };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-28"));
            Assert.AreEqual(1, r.Count);
        }
예제 #8
0
        public void DataTypes_RangeResolve_timerange_time_within_range()
        {
            var candidates  = new[] { "T16" };
            var constraints = new[] { (new TimexProperty {
                    Hour = 14, Hours = 4
                }).TimexValue };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("T16"));
            Assert.AreEqual(1, r.Count);
        }
예제 #9
0
        public void DataTypes_RangeResolve_duration_specific_time()
        {
            var constraints = new List <string>
            {
                "T19:30:00"
            };

            var result = TimexRangeResolver.Evaluate(new[] { "PT5M" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("T19:35"));
            Assert.AreEqual(1, r.Count);
        }
예제 #10
0
        public void DataTypes_RangeResolve_daterange_month_and_date_conditional()
        {
            var candidates  = new[] { "XXXX-05-29" };
            var constraints = new[] { "(2006-01-01,2008-06-01,P882D)" };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2006-05-29"));
            Assert.IsTrue(r.Contains("2007-05-29"));
            Assert.IsTrue(r.Contains("2008-05-29"));
            Assert.AreEqual(3, r.Count);
        }
예제 #11
0
        public void DataTypes_RangeResolve_adding_times_add_specific_time_to_date()
        {
            var constraints = new List <string>
            {
                "2017",
                "T19:30:00",
            };

            var result = TimexRangeResolver.Evaluate(new[] { "XXXX-05-29" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-05-29T19:30"));
            Assert.AreEqual(1, r.Count);
        }
예제 #12
0
        public void DataTypes_RangeResolve_duration_no_time_component()
        {
            var constraints = new List <string>
            {
                (new TimexProperty {
                    Year = 2017, Month = 10, DayOfMonth = 5, Days = 7
                }).TimexValue
            };

            var result = TimexRangeResolver.Evaluate(new[] { "PT5M" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsFalse(r.Any());
        }
예제 #13
0
        public void DataTypes_RangeResolve_daterange_month_and_date()
        {
            var candidates  = new[] { "XXXX-05-29" };
            var constraints = new[] { (new TimexProperty {
                    Year = 2006, Month = 1, DayOfMonth = 1, Years = 2
                }).TimexValue };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2006-05-29"));
            Assert.IsTrue(r.Contains("2007-05-29"));
            Assert.AreEqual(2, r.Count);
        }
예제 #14
0
        public void DataTypes_RangeResolve_filter_duplicate()
        {
            var constraints = new List <string> {
                (new TimexProperty {
                    Hour = 16, Hours = 4
                }).TimexValue
            };

            var result = TimexRangeResolver.Evaluate(new[] { "T16", "T16", "T16" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("T16"));
            Assert.AreEqual(1, r.Count);
        }
예제 #15
0
        public void DataTypes_RangeResolve_carry_through_time_definite()
        {
            var constraints = new List <string>
            {
                (new TimexProperty {
                    Year = 2017, Month = 9, DayOfMonth = 27, Days = 2
                }).TimexValue
            };

            var result = TimexRangeResolver.Evaluate(new[] { "2017-09-28T18:30:01" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-28T18:30:01"));
            Assert.AreEqual(1, r.Count);
        }
예제 #16
0
        public void DataTypes_RangeResolve_carry_through_time_multiple_constraints()
        {
            var constraints = new List <string>
            {
                "(2017-09-01,2017-09-08,P7D)",
                "(2017-10-01,2017-10-08,P7D)"
            };

            var result = TimexRangeResolver.Evaluate(new[] { "XXXX-WXX-3T01:02" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-06T01:02"));
            Assert.IsTrue(r.Contains("2017-10-04T01:02"));
            Assert.AreEqual(2, r.Count);
        }
예제 #17
0
        public void DataTypes_RangeResolve_daterange_Saturdays_in_September_expressed_as_range()
        {
            var candidates  = new[] { "XXXX-WXX-6" };
            var constraints = new[] { "(2017-09-01,2017-10-01,P30D)" };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-02"));
            Assert.IsTrue(r.Contains("2017-09-09"));
            Assert.IsTrue(r.Contains("2017-09-16"));
            Assert.IsTrue(r.Contains("2017-09-23"));
            Assert.IsTrue(r.Contains("2017-09-30"));
            Assert.AreEqual(5, r.Count);
        }
예제 #18
0
        public void DataTypes_RangeResolve_carry_through_time_Saturdays_in_September()
        {
            var constraints = new List <string> {
                "(2017-09-01,2017-10-01,P30D)"
            };

            var result = TimexRangeResolver.Evaluate(new[] { "XXXX-WXX-6T01:00:00" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-02T01"));
            Assert.IsTrue(r.Contains("2017-09-09T01"));
            Assert.IsTrue(r.Contains("2017-09-16T01"));
            Assert.IsTrue(r.Contains("2017-09-23T01"));
            Assert.IsTrue(r.Contains("2017-09-30T01"));
            Assert.AreEqual(5, r.Count);
        }
예제 #19
0
        public void DataTypes_RangeResolve_carry_through_time_month_and_date()
        {
            var constraints = new List <string>
            {
                new TimexProperty {
                    Year = 2006, Month = 1, DayOfMonth = 1, Years = 2
                }.TimexValue,
            };

            var result = TimexRangeResolver.Evaluate(new[] { "XXXX-05-29T19:30" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2006-05-29T19:30"));
            Assert.IsTrue(r.Contains("2007-05-29T19:30"));
            Assert.AreEqual(2, r.Count);
        }
예제 #20
0
        public void DataTypes_RangeResolve_dateranges_no_time_constraint()
        {
            var candidates  = new[] { "XXXX-WXX-7TEV" };
            var constraints = new[]
            {
                "(2018-06-04,2018-06-11,P7D)",  // e.g. this week
                "(2018-06-11,2018-06-18,P7D)",  // e.g. next week
            };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2018-06-10TEV"));
            Assert.IsTrue(r.Contains("2018-06-17TEV"));
            Assert.AreEqual(2, r.Count);
        }
예제 #21
0
        public static void Examples()
        {
            // When you give the recognzier the text "Wednesday 4 o'clock" you get these distinct TIMEX values back.

            // But our bot logic knows that whatever the user says it should be evaluated against the constraints of
            // a week from today with respect to the date part and in the evening with respect to the time part.

            var resolutions = TimexRangeResolver.Evaluate(
                new[] { "XXXX-WXX-3T04", "XXXX-WXX-3T16" },
                new[] { TimexCreator.WeekFromToday(), TimexCreator.Evening });

            var today = DateTime.Now;

            foreach (var resolution in resolutions)
            {
                Console.WriteLine(resolution.ToNaturalLanguage(today));
            }
        }
예제 #22
0
        public void DataTypes_RangeResolve_combined_daterange_and_timerange_next_week_and_business_hours()
        {
            var constraints = new List <string>
            {
                (new TimexProperty {
                    Year = 2017, Month = 10, DayOfMonth = 5, Days = 7
                }).TimexValue,
                (new TimexProperty {
                    Hour = 12, Minute = 0, Second = 0, Hours = 8
                }).TimexValue
            };

            var result = TimexRangeResolver.Evaluate(new[] { "XXXX-WXX-3T04", "XXXX-WXX-3T16" }, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-10-11T16"));
            Assert.AreEqual(1, r.Count);
        }
예제 #23
0
        // The notion of a Validator is a standard pattern across all the Prompts
        private static Task TimexValidator(ITurnContext context, TimexResult value)
        {
            var cadidates = value.Resolutions;

            var constraints = new[] { TimexCreator.ThisWeek(), TimexCreator.NextWeek(), TimexCreator.Evening };

            var resolutions = TimexRangeResolver.Evaluate(cadidates, constraints);

            if (resolutions.Count == 0)
            {
                value.Resolutions = new string[] {};
                value.Status      = PromptStatus.OutOfRange;
            }
            else
            {
                value.Resolutions = new[] { resolutions.First().TimexValue };
                value.Status      = PromptStatus.Recognized;
            }

            return(Task.CompletedTask);
        }
예제 #24
0
        public void DataTypes_RangeResolve_daterange_multiple_candidates_with_multiple_constraints()
        {
            var candidates = new[]
            {
                "XXXX-WXX-2",
                "XXXX-WXX-4"
            };
            var constraints = new[]
            {
                "(2017-09-01,2017-09-08,P7D)",
                "(2017-10-01,2017-10-08,P7D)"
            };

            var result = TimexRangeResolver.Evaluate(candidates, constraints);

            var r = new HashSet <string>(result.Select(t => t.TimexValue));

            Assert.IsTrue(r.Contains("2017-09-05"));
            Assert.IsTrue(r.Contains("2017-09-07"));
            Assert.IsTrue(r.Contains("2017-10-03"));
            Assert.IsTrue(r.Contains("2017-10-05"));
            Assert.AreEqual(4, r.Count);
        }
        public static ReservationResult Validate(OnTurnProperty onTurnProperty, ReservationResult returnResult)
        {
            if (onTurnProperty == null || onTurnProperty.Entities.Count == 0)
            {
                return(returnResult);
            }

            // We only will pull number -> party size, datetimeV2 -> date and time, cafeLocation -> location.
            var numberEntity       = onTurnProperty.Entities.Find(item => item.EntityName.Equals(PartySizeEntity));
            var dateTimeEntity     = onTurnProperty.Entities.Find(item => item.EntityName.Equals(DateTimeEntity));
            var locationEntity     = onTurnProperty.Entities.Find(item => item.EntityName.Equals(LocationEntity));
            var confirmationEntity = onTurnProperty.Entities.Find(item => item.EntityName.Equals(ConfirmationEntity));

            if (numberEntity != null)
            {
                // We only accept MaxPartySize in a reservation.
                var partySize = int.Parse(numberEntity.Value as string);
                if (partySize > MaxPartySize)
                {
                    returnResult.Outcome.Add(new ReservationOutcome($"Sorry. {int.Parse(numberEntity.Value as string)} does not work. I can only accept up to 10 guests in a reservation.", PartySizeEntity));
                    returnResult.Status = ReservationStatus.Incomplete;
                }
                else
                {
                    returnResult.NewReservation.PartySize = partySize;
                }
            }

            if (dateTimeEntity != null)
            {
                // Get parsed date time from TIMEX
                // LUIS returns a timex expression and so get and un-wrap that.
                // Take the first date time since book table scenario does not have to deal with multiple date times or date time ranges.
                var timexProp = ((JToken)dateTimeEntity.Value)?["timex"]?[0]?.ToString();
                if (timexProp != null)
                {
                    var today       = DateTime.Now;
                    var parsedTimex = new TimexProperty(timexProp);

                    // Validate the date (and check constraints (later))
                    if (parsedTimex.DayOfMonth != null && parsedTimex.Year != null && parsedTimex.Month != null)
                    {
                        var date = DateTimeOffset.Parse($"{parsedTimex.Year}-{parsedTimex.Month}-{parsedTimex.DayOfMonth}");
                        returnResult.NewReservation.Date         = date.UtcDateTime.ToString("o").Split("T")[0];
                        returnResult.NewReservation.DateLGString = new TimexProperty(returnResult.NewReservation.Date).ToNaturalLanguage(today);
                    }

                    // See if the time meets our constraints.
                    if (parsedTimex.Hour != null &&
                        parsedTimex.Minute != null &&
                        parsedTimex.Second != null)
                    {
                        var timexOptions = ((JToken)dateTimeEntity.Value)?["timex"]?.ToObject <List <string> >();

                        var validtime = TimexRangeResolver.Evaluate(timexOptions, reservationTimeConstraints);

                        returnResult.NewReservation.Time  = ((int)parsedTimex.Hour).ToString("D2");
                        returnResult.NewReservation.Time += ":";
                        returnResult.NewReservation.Time += ((int)parsedTimex.Minute).ToString("D2");
                        returnResult.NewReservation.Time += ":";
                        returnResult.NewReservation.Time += ((int)parsedTimex.Second).ToString("D2");

                        if (validtime == null || (validtime.Count == 0))
                        {
                            // Validation failed!
                            returnResult.Outcome.Add(new ReservationOutcome("Sorry, that time does not work. I can only make reservations that are in the daytime (6AM - 6PM)", DateTimeEntity));
                            returnResult.NewReservation.Time = string.Empty;
                            returnResult.Status = ReservationStatus.Incomplete;
                        }
                    }

                    // Get date time LG string if we have both date and time.
                    if (!string.IsNullOrWhiteSpace(returnResult.NewReservation.Date) && !string.IsNullOrWhiteSpace(returnResult.NewReservation.Time))
                    {
                        returnResult.NewReservation.DateTimeLGString = new TimexProperty(returnResult.NewReservation.Date + "T" + returnResult.NewReservation.Time).ToNaturalLanguage(today);
                    }
                }
            }

            // Take the first found value.
            if (locationEntity != null)
            {
                var cafeLocation = locationEntity.Value;

                // Capitalize cafe location.
                returnResult.NewReservation.Location = char.ToUpper(((string)cafeLocation)[0]) + ((string)cafeLocation).Substring(1);
            }

            // Accept confirmation entity if available only if we have a complete reservation
            if (confirmationEntity != null)
            {
                var value = confirmationEntity.Value as string;
                if (value != null && value == "yes")
                {
                    returnResult.NewReservation.ReservationConfirmed = true;
                    returnResult.NewReservation.NeedsChange          = false;
                }
                else
                {
                    returnResult.NewReservation.NeedsChange          = true;
                    returnResult.NewReservation.ReservationConfirmed = false;
                }
            }

            return(returnResult);
        }