// Examines the LUIS response for entities, namely a location for the weather forecast. // <returns>String containing the entities, if any.</returns> private LUISEntities ParseLuisForEntities(RecognizerResult recognizerResult) { LUISEntities result = new LUISEntities(); var temp = recognizerResult.Entities.First; // recognizerResult.Entities returns type JObject. foreach (var entity in recognizerResult.Entities) { // use JsonConvert to convert entity.Value to a dynamic object. dynamic o = JsonConvert.DeserializeObject <dynamic>(entity.Value.ToString()); if (result.Location.Equals(string.Empty)) { // Take the first entity if (o.location != null) { // Grab first location entry result.Location = o.location[0].text; // Since it's a location, make sure first letter is capitalized result.Location = result.Location.First().ToString().ToUpper() + result.Location.Substring(1); } } if (result.Condition.Equals(string.Empty)) { // Take the first entity if (o.condition != null) { result.Condition = o.condition[0].text; } } if (result.Sun.Equals(string.Empty)) { // Take the first entity if (o.sun != null) { result.Sun = o.sun[0].text; } } // If we found entities, they will be together in the same entry. Return those results. if (result.Sun.Equals(string.Empty) && result.Condition.Equals(string.Empty) && result.Location.Equals(string.Empty)) { continue; } return(result); } // No entities found. return(result); }
private JObject GetForecastInformation(string forecastType, LUISEntities entityFound) { string forecastUrl = string.Empty; switch (forecastType) { case DailyForecast: forecastUrl = "http://api.openweathermap.org/data/2.5/weather?q=" + entityFound.Location + "&APPID=" + openMapKey; break; case HourlyForecast: forecastUrl = "http://api.openweathermap.org/data/2.5/forecast?q=" + entityFound.Location + "&APPID=" + openMapKey; break; default: throw new InvalidOperationException($"Invalid forecast type requested."); } return(GetFormattedJSON(forecastUrl)); }
// Finds the hourly forecast from provided forecast information. private string FindHourlyForecast(JObject json, LUISEntities entities) { string hourlyForecastString = $"Hourly weather forecasts for {entities.Location}.\n"; string hourlyTempString = "00.00"; string hourlyConditionString = "cloudy"; string hourlyTimeString = string.Empty; string conditionString = string.Empty; string conditionStart = string.Empty; string condition = entities.Condition; int counter = 0; if (condition != string.Empty) { // Truncate string for grammar for precipitation condition = condition.Replace("ing", string.Empty); condition = condition.Replace("sunny", "sun"); condition = condition.Replace("cloudy", "clouds"); condition = condition.Replace("y", string.Empty); } // LINQ query to get the list of hourly forecasts var hourlyForecast = from f in json["list"] select f; foreach (var forecast in hourlyForecast) { // Get the temp and convert it. hourlyTempString = FindCurrentTemp(forecast as JObject); // Get the conditions. hourlyConditionString = FindCurrentConditions(forecast as JObject); // Get the current time from the forecast. DateTime start_time = (DateTime)forecast["dt_txt"]; // Convert from UTC to local time. start_time = start_time.ToLocalTime(); // Add 90 minutes to get to the middle of the interval. start_time += new TimeSpan(1, 30, 0); hourlyTimeString = start_time.ToShortTimeString(); if (!condition.Equals(string.Empty) && hourlyConditionString.Contains(condition) && conditionStart.Equals(string.Empty)) { conditionStart = hourlyTimeString + "\n"; } // Build the forecast string from information above and append it. hourlyForecastString = hourlyForecastString + "Forecast for: " + hourlyTimeString + ", Temperature: " + hourlyTempString + "F, " + hourlyConditionString + "\n"; // Only give first 8, which is a full day. counter++; if (counter > 7) { break; } } if (!condition.Equals(string.Empty)) { if (conditionStart.Equals(string.Empty)) { conditionString = "There isn't any " + condition + " in the forecast for the next 24 hours!\n"; } else { conditionString = "It looks like you will see " + condition + " by about " + conditionStart + "\n"; } } return(conditionString + hourlyForecastString); }
private async Task ProcessWeatherAsync(ITurnContext <IMessageActivity> turnContext, LuisResult luisResult, CancellationToken cancellationToken) { // Get the state properties. var conversationStateAccessors = _conversationState.CreateProperty <ConversationData>(nameof(ConversationData)); var conversationData = await conversationStateAccessors.GetAsync(turnContext, () => new ConversationData()); var userStateAccessors = _userState.CreateProperty <UserProfile>(nameof(UserProfile)); var userProfile = await userStateAccessors.GetAsync(turnContext, () => new UserProfile()); await turnContext.SendActivityAsync(MessageFactory.Text($"Sending your request to Luis."), cancellationToken); _logger.LogInformation("ProcessWeatherAsync"); openMapKey = _configuration["OpenWeatherMapKey"]; conversationData.DispatchIntent = luisResult.TopScoringIntent.Intent; var results = await _botServices.Forecasts.RecognizeAsync(turnContext, cancellationToken); // Top intent tells us which cognitive service to use. var topIntent = results.GetTopScoringIntent(); conversationData.LuisIntent = topIntent.intent; // uncomment to debug returned weather intents. // await turnContext.SendActivityAsync(MessageFactory.Text($"Forecasts intent returned {topIntent.intent}."), cancellationToken); // See if LUIS found and used an entity to determine user intent. LUISEntities entityFound = ParseLuisForEntities(results); // save all returned entities within conversationData conversationData.Location = entityFound.Location; conversationData.Condition = entityFound.Condition; conversationData.Sun = entityFound.Sun; if (entityFound.Location == string.Empty) { if ((userProfile.Location != null) && (userProfile.Location != string.Empty)) { entityFound.Location = userProfile.Location; conversationData.Location = userProfile.Location; } else { // Inform the user we found no location. await turnContext.SendActivityAsync("Sorry, no location was provided for your request. Please add a phrase like 'in Redmond' to your weather question."); } } else { // Save the location this user asked about for later use as well. userProfile.Location = entityFound.Location; } if (topIntent.intent != null && topIntent.intent != "None") { string debugInfo = string.Empty; // $"==> LUIS Top Scoring Intent: { topIntent.Value.intent}, LUIS location entity: { entityFound.Location}, Score: { topIntent.Value.score}\n "; if (entityFound.Location != string.Empty && topIntent.intent == "Daily_Forecast") { // Use top intent and "entityFound" = location to call daily weather service here... var jsonResult = GetForecastInformation(DailyForecast, entityFound); var currentConditions = FindCurrentConditions(jsonResult); var currentTemp = FindCurrentTemp(jsonResult); await turnContext.SendActivityAsync(debugInfo + $"Daily weather forecast for {entityFound.Location}.\n {currentConditions}, temperature: {currentTemp}F"); } else if (entityFound.Location != string.Empty && topIntent.intent == "Hourly_Forecast") { // Use top intent and "entityFound" = location to call hourly weather service here... var jsonResult = GetForecastInformation(HourlyForecast, entityFound); // Call FindHourlyForecast var currentForecast = FindHourlyForecast(jsonResult, entityFound); await turnContext.SendActivityAsync(debugInfo + currentForecast); } else if (entityFound.Location != string.Empty && topIntent.intent == "When_Condition") { // Get forecast information var jsonResult = GetForecastInformation(HourlyForecast, entityFound); // Find when that condition is happening var currentForecast = FindHourlyForecast(jsonResult, entityFound); await turnContext.SendActivityAsync(debugInfo + currentForecast); } else if (entityFound.Location != string.Empty && topIntent.intent == "When_Sun") { // Get forecast information var jsonResult = GetForecastInformation(DailyForecast, entityFound); var sunStatus = FindSunTime(jsonResult, entityFound.Sun); await turnContext.SendActivityAsync($"Today in {entityFound.Location} the sun will " + sunStatus); } else if (topIntent.intent == "User_Goodbye") { // Say goodbye. await SignOutUser(turnContext); } } else { var msg = @"Try weather inputs like: 'Show me weather for Redmond.' or 'Will it rain in Redmond?'."; await turnContext.SendActivityAsync(msg); } }