-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathTimeSurveyBotLuisEx.cs
More file actions
154 lines (137 loc) · 6.82 KB
/
TimeSurveyBotLuisEx.cs
File metadata and controls
154 lines (137 loc) · 6.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Bot.Builder.AI.Luis;
using Microsoft.Recognizers.Text;
using Microsoft.Recognizers.Text.DateTime;
namespace Bot.Common.Recognizer
{
public partial class TimeSurveyBotLuis
{
public Intent TopIntentWithMinScore(double minScore = 0.75)
{
(var topIntent, double score) = TopIntent();
return score < minScore ? Intent.None : topIntent;
}
public string ProjectName()
{
var workedEntityInstances = Entities._instance.WorkedEntity;
if (
workedEntityInstances == null ||
workedEntityInstances.Length == 0 ||
Enumerable.First<InstanceData>(workedEntityInstances).Text == null
)
{
throw new InvalidWorkedEntityException("No worked entity has been recognized");
}
return Enumerable.First<InstanceData>(workedEntityInstances).Text;
}
public string WorkedDuration()
{
var workedPeriodInstances = Entities._instance.datetime;
if (
workedPeriodInstances == null ||
workedPeriodInstances.Length == 0 ||
workedPeriodInstances.First<InstanceData>().Text == null)
{
throw new InvalidWorkedDurationException("No worked duration has been recognized");
}
return workedPeriodInstances.First<InstanceData>().Text;
}
public double WorkedDurationInMinutes(string culture = Culture.English)
{
string timePeriod = WorkedDuration();
try
{
var recognizedDateTime = DateTimeRecognizer.RecognizeDateTime(timePeriod, culture).First();
var resolvedDateTime = ((List<Dictionary<string, string>>)recognizedDateTime.Resolution["values"])[0];
string dateTimeType = resolvedDateTime["type"];
if (dateTimeType.Equals("duration"))
{
string recognizedSeconds = resolvedDateTime["value"];
return double.Parse(recognizedSeconds) / 60;
}
throw new InvalidWorkedDurationException(
$"No worked duration has been recognized. Type {dateTimeType} not supported.");
}
catch (Exception ex) when (
ex is FormatException ||
ex is InvalidOperationException
)
{
throw new InvalidWorkedEntityException("No worked duration has been recognized");
}
}
public (DateTime start, DateTime end) WorkedPeriod(IDateTimeProvider dateTimeProvider, double minutes, TimeZoneInfo timeZone,
string culture = Culture.English)
{
var workedPeriodInstances = Entities._instance.datetime;
var userNow = TimeZoneInfo.ConvertTime(dateTimeProvider.DateTimeUtcNow(), timeZone);
if (workedPeriodInstances.Length > 1)
{
string? instance = workedPeriodInstances[1].Text;
var recognizedDateTime =
DateTimeRecognizer.RecognizeDateTime(instance, culture, refTime: userNow).First();
var resolvedPeriod = ((List<Dictionary<string, string>>)recognizedDateTime.Resolution["values"])[0];
return RecognizedWorkedPeriod(userNow, resolvedPeriod, minutes, timeZone);
}
var thisMorning = userNow.Date.AddHours(9);
var thisMorningUtc = TimeZoneInfo.ConvertTimeToUtc(thisMorning, timeZone);
return (thisMorningUtc, thisMorningUtc.AddMinutes(minutes));
}
private static (DateTime start, DateTime end) RecognizedWorkedPeriod(DateTime refTime,
IReadOnlyDictionary<string, string> periodData, double minutes, TimeZoneInfo timeZone)
{
string dateTimeType = periodData["type"];
if (dateTimeType.Equals("date"))
{
var date = DateTime.Parse(periodData["value"]);
var start = new DateTime(date.Year, date.Month, date.Day, 9, 0, 0);
var startUtc = TimeZoneInfo.ConvertTimeToUtc(start, timeZone);
return (startUtc, startUtc.AddMinutes(minutes));
}
if (dateTimeType.Equals("datetime"))
{
var datetime = ParseToUtc(periodData["value"], timeZone);
return (datetime, datetime.AddMinutes(minutes));
}
if (dateTimeType.Equals("timerange") && periodData.ContainsKey("Mod") && periodData["Mod"].Equals("before"))
{
var time = ParseToUtc(periodData["end"], timeZone);
var datetime = new DateTime(refTime.Year, refTime.Month, refTime.Day, time.Hour, time.Minute,
time.Second);
return (datetime.Subtract(TimeSpan.FromMinutes(minutes)), datetime);
}
if (dateTimeType.Equals("timerange") && periodData.ContainsKey("Mod") && periodData["Mod"].Equals("since"))
{
var time = ParseToUtc(periodData["start"], timeZone);
var datetime = new DateTime(refTime.Year, refTime.Month, refTime.Day, time.Hour, time.Minute,
time.Second);
return (datetime, datetime.AddMinutes(minutes));
}
if (dateTimeType.Equals("timerange") && !periodData.ContainsKey("Mod"))
{
var timeStart = ParseToUtc(periodData["start"], timeZone);
var datetimeStart = new DateTime(refTime.Year, refTime.Month, refTime.Day, timeStart.Hour,
timeStart.Minute, timeStart.Second);
var timeEnd = ParseToUtc(periodData["end"], timeZone);
var datetimeEnd = new DateTime(refTime.Year, refTime.Month, refTime.Day, timeEnd.Hour,
timeEnd.Minute, timeEnd.Second);
double minutesBetweenDates = datetimeEnd.Subtract(datetimeStart).TotalMinutes;
// Floating point comparison, we check that the difference is greater than one minute.
if (Math.Abs(minutesBetweenDates - minutes) > 1)
{
throw new InvalidWorkedPeriodException(
$"Worked period time span differs from the duration provided. Expected {minutes} but got {minutesBetweenDates}");
}
return (datetimeStart, datetimeEnd);
}
throw new InvalidWorkedPeriodException($"Date time type {dateTimeType} is not allowed");
}
private static DateTime ParseToUtc(string localDateTimeString, TimeZoneInfo timeZone)
{
var localDt = DateTime.Parse(localDateTimeString);
return TimeZoneInfo.ConvertTimeToUtc(localDt, timeZone);
}
}
}