Extract command route builders from JiboInteractionService
This commit is contained in:
@@ -0,0 +1,252 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Jibo.Cloud.Application.Abstractions;
|
||||||
|
using Jibo.Cloud.Domain.Models;
|
||||||
|
using Jibo.Runtime.Abstractions;
|
||||||
|
|
||||||
|
namespace Jibo.Cloud.Application.Services;
|
||||||
|
|
||||||
|
public sealed partial class JiboInteractionService
|
||||||
|
{
|
||||||
|
private static JiboInteractionDecision BuildCurrentLocationDecision(TurnContext turn)
|
||||||
|
{
|
||||||
|
var locationName = TryResolveCurrentLocationName(turn);
|
||||||
|
if (string.IsNullOrWhiteSpace(locationName))
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"current_location",
|
||||||
|
"I'm not sure where we are right now.");
|
||||||
|
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"current_location",
|
||||||
|
$"We're at {NormalizeLocationForSpeech(locationName)} if I'm not mistaken.",
|
||||||
|
ContextUpdates: ScriptedResponseDecisionBuilder.BuildScriptedResponseContextUpdates());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildOrderPizzaDecision()
|
||||||
|
{
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"order_pizza",
|
||||||
|
"I can't do that yet, but I bet I'll be able to do that sometime in the near future.",
|
||||||
|
"chitchat-skill",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["esml"] =
|
||||||
|
"<speak>I can't do that yet, but I bet I'll be able to do that sometime in the near future.</speak>",
|
||||||
|
["mim_id"] = "RA_JBO_OrderPizza",
|
||||||
|
["mim_type"] = "announcement",
|
||||||
|
["prompt_id"] = "RA_JBO_OrderPizza_AN_01",
|
||||||
|
["prompt_sub_category"] = "AN"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private JiboInteractionDecision BuildJokeDecision(JiboExperienceCatalog catalog)
|
||||||
|
{
|
||||||
|
var joke = randomizer.Choose(catalog.Jokes);
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"joke",
|
||||||
|
joke,
|
||||||
|
"@be/joke",
|
||||||
|
new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["replyType"] = "joke"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private JiboInteractionDecision BuildRandomDanceDecision(JiboExperienceCatalog catalog)
|
||||||
|
{
|
||||||
|
var dance = randomizer.Choose(catalog.DanceAnimations);
|
||||||
|
var replyText = randomizer.Choose(catalog.DanceReplies);
|
||||||
|
return BuildDanceDecision("dance", dance, replyText);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JiboInteractionDecision BuildDanceQuestionDecision(JiboExperienceCatalog catalog)
|
||||||
|
{
|
||||||
|
return new JiboInteractionDecision("dance_question", randomizer.Choose(catalog.DanceQuestionReplies));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildDanceDecision(string intentName, string dance, string replyText)
|
||||||
|
{
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
intentName,
|
||||||
|
replyText,
|
||||||
|
"chitchat-skill",
|
||||||
|
new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["esml"] =
|
||||||
|
$"<speak>Okay.<break size='0.2'/> Watch this.<anim cat='dance' filter='music, {dance}' /></speak>",
|
||||||
|
["mim_id"] = "runtime-chat",
|
||||||
|
["mim_type"] = "announcement"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildVolumeControlDecision(string intentName, string globalIntent,
|
||||||
|
string globalValue)
|
||||||
|
{
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
intentName,
|
||||||
|
"Opening volume controls.",
|
||||||
|
"global_commands",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["skillId"] = "@be/settings",
|
||||||
|
["globalIntent"] = globalIntent,
|
||||||
|
["volumeLevel"] = globalValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildSettingsVolumeDecision()
|
||||||
|
{
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"volume_query",
|
||||||
|
"Opening volume controls.",
|
||||||
|
"@be/settings",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["skillId"] = "@be/settings",
|
||||||
|
["localIntent"] = "volumeQuery"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildClockLaunchDecision(string intentName, string domain,
|
||||||
|
string clockIntent, string replyText)
|
||||||
|
{
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
intentName,
|
||||||
|
replyText,
|
||||||
|
"@be/clock",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["skillId"] = "@be/clock",
|
||||||
|
["domain"] = domain,
|
||||||
|
["clockIntent"] = clockIntent
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildClockLaunchDecision(string domain, string replyText)
|
||||||
|
{
|
||||||
|
return BuildClockLaunchDecision($"{domain}_menu", domain, "menu", replyText);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildClockClarifyDecision(string intentName, string domain, string replyText)
|
||||||
|
{
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
intentName,
|
||||||
|
replyText,
|
||||||
|
"@be/clock",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["skillId"] = "@be/clock",
|
||||||
|
["domain"] = domain,
|
||||||
|
["clockIntent"] = "set"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildTimerValueDecision(
|
||||||
|
string loweredTranscript,
|
||||||
|
bool allowImplicit,
|
||||||
|
IReadOnlyDictionary<string, string> clientEntities)
|
||||||
|
{
|
||||||
|
var timer = TryReadStructuredTimerValue(clientEntities) ??
|
||||||
|
TryParseTimerValue(loweredTranscript, allowImplicit) ??
|
||||||
|
new ClockTimerValue("0", "1", "null");
|
||||||
|
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"timer_value",
|
||||||
|
"Setting your timer.",
|
||||||
|
"@be/clock",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["skillId"] = "@be/clock",
|
||||||
|
["domain"] = "timer",
|
||||||
|
["clockIntent"] = "start",
|
||||||
|
["hours"] = timer.Hours,
|
||||||
|
["minutes"] = timer.Minutes,
|
||||||
|
["seconds"] = timer.Seconds
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildAlarmValueDecision(
|
||||||
|
string loweredTranscript,
|
||||||
|
bool allowImplicit,
|
||||||
|
DateTimeOffset? referenceLocalTime,
|
||||||
|
IReadOnlyDictionary<string, string> clientEntities)
|
||||||
|
{
|
||||||
|
var alarm = TryReadStructuredAlarmValue(clientEntities) ??
|
||||||
|
TryParseAlarmValue(loweredTranscript, allowImplicit, referenceLocalTime) ??
|
||||||
|
new ClockAlarmValue("7:00", "am");
|
||||||
|
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"alarm_value",
|
||||||
|
"Setting your alarm.",
|
||||||
|
"@be/clock",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["skillId"] = "@be/clock",
|
||||||
|
["domain"] = "alarm",
|
||||||
|
["clockIntent"] = "start",
|
||||||
|
["time"] = alarm.Time,
|
||||||
|
["ampm"] = alarm.AmPm
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildRadioGenreLaunchDecision(string loweredTranscript)
|
||||||
|
{
|
||||||
|
var station = TryResolveRadioGenre(loweredTranscript) ?? "Country";
|
||||||
|
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"radio_genre",
|
||||||
|
$"Playing {FormatRadioGenreForSpeech(station)} on the radio.",
|
||||||
|
"@be/radio",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["skillId"] = "@be/radio",
|
||||||
|
["station"] = station
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JiboInteractionDecision BuildWordOfTheDayGuessDecision(
|
||||||
|
IReadOnlyDictionary<string, string> clientEntities,
|
||||||
|
string transcript,
|
||||||
|
IReadOnlyList<string> listenAsrHints)
|
||||||
|
{
|
||||||
|
var guess = ResolveWordOfTheDayGuess(clientEntities, transcript, listenAsrHints);
|
||||||
|
|
||||||
|
var reply = string.IsNullOrWhiteSpace(guess)
|
||||||
|
? "I heard your word of the day guess."
|
||||||
|
: $"I heard {guess}.";
|
||||||
|
|
||||||
|
return new JiboInteractionDecision(
|
||||||
|
"word_of_the_day_guess",
|
||||||
|
reply,
|
||||||
|
"@be/word-of-the-day",
|
||||||
|
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["guess"] = guess,
|
||||||
|
["skillId"] = "@be/word-of-the-day",
|
||||||
|
["cloudResponseMode"] = "completion_only"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveWordOfTheDayGuess(
|
||||||
|
IReadOnlyDictionary<string, string> clientEntities,
|
||||||
|
string transcript,
|
||||||
|
IReadOnlyList<string> listenAsrHints)
|
||||||
|
{
|
||||||
|
if (clientEntities.TryGetValue("guess", out var guessValue) &&
|
||||||
|
!string.IsNullOrWhiteSpace(guessValue))
|
||||||
|
return guessValue;
|
||||||
|
|
||||||
|
var loweredTranscript = NormalizeGuessToken(transcript);
|
||||||
|
var hintIndex = loweredTranscript switch
|
||||||
|
{
|
||||||
|
"1" or "one" or "first" => 0,
|
||||||
|
"2" or "two" or "second" => 1,
|
||||||
|
"3" or "three" or "third" => 2,
|
||||||
|
_ => -1
|
||||||
|
};
|
||||||
|
|
||||||
|
if (hintIndex >= 0 && hintIndex < listenAsrHints.Count) return listenAsrHints[hintIndex];
|
||||||
|
|
||||||
|
var fuzzyHintMatch = FindClosestHint(loweredTranscript, listenAsrHints);
|
||||||
|
return !string.IsNullOrWhiteSpace(fuzzyHintMatch) ? fuzzyHintMatch : transcript;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,15 @@ namespace Jibo.Cloud.Application.Services;
|
|||||||
|
|
||||||
public sealed partial class JiboInteractionService
|
public sealed partial class JiboInteractionService
|
||||||
{
|
{
|
||||||
|
private static string EscapeForEsml(string value)
|
||||||
|
{
|
||||||
|
return value
|
||||||
|
.Replace("&", "&", StringComparison.Ordinal)
|
||||||
|
.Replace("<", "<", StringComparison.Ordinal)
|
||||||
|
.Replace(">", ">", StringComparison.Ordinal)
|
||||||
|
.Replace("\"", """, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
private static string BuildWeatherSpokenReply(
|
private static string BuildWeatherSpokenReply(
|
||||||
WeatherReportSnapshot snapshot,
|
WeatherReportSnapshot snapshot,
|
||||||
WeatherDateEntity weatherDate,
|
WeatherDateEntity weatherDate,
|
||||||
|
|||||||
@@ -803,88 +803,6 @@ public sealed partial class JiboInteractionService(
|
|||||||
SkillPayload: new Dictionary<string, object?> { ["esml"] = OpenJiboCloudBuildInfo.EsmlVersion });
|
SkillPayload: new Dictionary<string, object?> { ["esml"] = OpenJiboCloudBuildInfo.EsmlVersion });
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildCurrentLocationDecision(TurnContext turn)
|
|
||||||
{
|
|
||||||
var locationName = TryResolveCurrentLocationName(turn);
|
|
||||||
if (string.IsNullOrWhiteSpace(locationName))
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"current_location",
|
|
||||||
"I'm not sure where we are right now.");
|
|
||||||
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"current_location",
|
|
||||||
$"We're at {NormalizeLocationForSpeech(locationName)} if I'm not mistaken.",
|
|
||||||
ContextUpdates: ScriptedResponseDecisionBuilder.BuildScriptedResponseContextUpdates());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static string EscapeForEsml(string value)
|
|
||||||
{
|
|
||||||
return value
|
|
||||||
.Replace("&", "&", StringComparison.Ordinal)
|
|
||||||
.Replace("<", "<", StringComparison.Ordinal)
|
|
||||||
.Replace(">", ">", StringComparison.Ordinal)
|
|
||||||
.Replace("\"", """, StringComparison.Ordinal);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildOrderPizzaDecision()
|
|
||||||
{
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"order_pizza",
|
|
||||||
"I can't do that yet, but I bet I'll be able to do that sometime in the near future.",
|
|
||||||
"chitchat-skill",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["esml"] =
|
|
||||||
"<speak>I can't do that yet, but I bet I'll be able to do that sometime in the near future.</speak>",
|
|
||||||
["mim_id"] = "RA_JBO_OrderPizza",
|
|
||||||
["mim_type"] = "announcement",
|
|
||||||
["prompt_id"] = "RA_JBO_OrderPizza_AN_01",
|
|
||||||
["prompt_sub_category"] = "AN"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private JiboInteractionDecision BuildJokeDecision(JiboExperienceCatalog catalog)
|
|
||||||
{
|
|
||||||
var joke = randomizer.Choose(catalog.Jokes);
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"joke",
|
|
||||||
joke,
|
|
||||||
"@be/joke",
|
|
||||||
new Dictionary<string, object?>
|
|
||||||
{
|
|
||||||
["replyType"] = "joke"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private JiboInteractionDecision BuildRandomDanceDecision(JiboExperienceCatalog catalog)
|
|
||||||
{
|
|
||||||
var dance = randomizer.Choose(catalog.DanceAnimations);
|
|
||||||
var replyText = randomizer.Choose(catalog.DanceReplies);
|
|
||||||
return BuildDanceDecision("dance", dance, replyText);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JiboInteractionDecision BuildDanceQuestionDecision(JiboExperienceCatalog catalog)
|
|
||||||
{
|
|
||||||
return new JiboInteractionDecision("dance_question", randomizer.Choose(catalog.DanceQuestionReplies));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildDanceDecision(string intentName, string dance, string replyText)
|
|
||||||
{
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
intentName,
|
|
||||||
replyText,
|
|
||||||
"chitchat-skill",
|
|
||||||
new Dictionary<string, object?>
|
|
||||||
{
|
|
||||||
["esml"] =
|
|
||||||
$"<speak>Okay.<break size='0.2'/> Watch this.<anim cat='dance' filter='music, {dance}' /></speak>",
|
|
||||||
["mim_id"] = "runtime-chat",
|
|
||||||
["mim_type"] = "announcement"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private JiboInteractionDecision BuildSurpriseDecision(
|
private JiboInteractionDecision BuildSurpriseDecision(
|
||||||
JiboExperienceCatalog catalog,
|
JiboExperienceCatalog catalog,
|
||||||
TurnContext turn,
|
TurnContext turn,
|
||||||
@@ -1081,176 +999,4 @@ public sealed partial class JiboInteractionService(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildVolumeControlDecision(string intentName, string globalIntent,
|
|
||||||
string volumeLevel)
|
|
||||||
{
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
intentName,
|
|
||||||
"Adjusting volume.",
|
|
||||||
"global_commands",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["globalIntent"] = globalIntent,
|
|
||||||
["nluDomain"] = "global_commands",
|
|
||||||
["volumeLevel"] = volumeLevel
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildSettingsVolumeDecision()
|
|
||||||
{
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"volume_query",
|
|
||||||
"Opening volume controls.",
|
|
||||||
"@be/settings",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["skillId"] = "@be/settings",
|
|
||||||
["localIntent"] = "volumeQuery"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildClockLaunchDecision(string intentName, string domain,
|
|
||||||
string clockIntent, string replyText)
|
|
||||||
{
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
intentName,
|
|
||||||
replyText,
|
|
||||||
"@be/clock",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["skillId"] = "@be/clock",
|
|
||||||
["domain"] = domain,
|
|
||||||
["clockIntent"] = clockIntent
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildClockLaunchDecision(string domain, string replyText)
|
|
||||||
{
|
|
||||||
return BuildClockLaunchDecision($"{domain}_menu", domain, "menu", replyText);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildClockClarifyDecision(string intentName, string domain, string replyText)
|
|
||||||
{
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
intentName,
|
|
||||||
replyText,
|
|
||||||
"@be/clock",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["skillId"] = "@be/clock",
|
|
||||||
["domain"] = domain,
|
|
||||||
["clockIntent"] = "set"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildTimerValueDecision(
|
|
||||||
string loweredTranscript,
|
|
||||||
bool allowImplicit,
|
|
||||||
IReadOnlyDictionary<string, string> clientEntities)
|
|
||||||
{
|
|
||||||
var timer = TryReadStructuredTimerValue(clientEntities) ??
|
|
||||||
TryParseTimerValue(loweredTranscript, allowImplicit) ??
|
|
||||||
new ClockTimerValue("0", "1", "null");
|
|
||||||
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"timer_value",
|
|
||||||
"Setting your timer.",
|
|
||||||
"@be/clock",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["skillId"] = "@be/clock",
|
|
||||||
["domain"] = "timer",
|
|
||||||
["clockIntent"] = "start",
|
|
||||||
["hours"] = timer.Hours,
|
|
||||||
["minutes"] = timer.Minutes,
|
|
||||||
["seconds"] = timer.Seconds
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildAlarmValueDecision(
|
|
||||||
string loweredTranscript,
|
|
||||||
bool allowImplicit,
|
|
||||||
DateTimeOffset? referenceLocalTime,
|
|
||||||
IReadOnlyDictionary<string, string> clientEntities)
|
|
||||||
{
|
|
||||||
var alarm = TryReadStructuredAlarmValue(clientEntities) ??
|
|
||||||
TryParseAlarmValue(loweredTranscript, allowImplicit, referenceLocalTime) ??
|
|
||||||
new ClockAlarmValue("7:00", "am");
|
|
||||||
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"alarm_value",
|
|
||||||
"Setting your alarm.",
|
|
||||||
"@be/clock",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["skillId"] = "@be/clock",
|
|
||||||
["domain"] = "alarm",
|
|
||||||
["clockIntent"] = "start",
|
|
||||||
["time"] = alarm.Time,
|
|
||||||
["ampm"] = alarm.AmPm
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildRadioGenreLaunchDecision(string loweredTranscript)
|
|
||||||
{
|
|
||||||
var station = TryResolveRadioGenre(loweredTranscript) ?? "Country";
|
|
||||||
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"radio_genre",
|
|
||||||
$"Playing {FormatRadioGenreForSpeech(station)} on the radio.",
|
|
||||||
"@be/radio",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["skillId"] = "@be/radio",
|
|
||||||
["station"] = station
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildWordOfTheDayGuessDecision(
|
|
||||||
IReadOnlyDictionary<string, string> clientEntities,
|
|
||||||
string transcript,
|
|
||||||
IReadOnlyList<string> listenAsrHints)
|
|
||||||
{
|
|
||||||
var guess = ResolveWordOfTheDayGuess(clientEntities, transcript, listenAsrHints);
|
|
||||||
|
|
||||||
var reply = string.IsNullOrWhiteSpace(guess)
|
|
||||||
? "I heard your word of the day guess."
|
|
||||||
: $"I heard {guess}.";
|
|
||||||
|
|
||||||
return new JiboInteractionDecision(
|
|
||||||
"word_of_the_day_guess",
|
|
||||||
reply,
|
|
||||||
"@be/word-of-the-day",
|
|
||||||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
["guess"] = guess,
|
|
||||||
["skillId"] = "@be/word-of-the-day",
|
|
||||||
["cloudResponseMode"] = "completion_only"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ResolveWordOfTheDayGuess(
|
|
||||||
IReadOnlyDictionary<string, string> clientEntities,
|
|
||||||
string transcript,
|
|
||||||
IReadOnlyList<string> listenAsrHints)
|
|
||||||
{
|
|
||||||
if (clientEntities.TryGetValue("guess", out var guessValue) &&
|
|
||||||
!string.IsNullOrWhiteSpace(guessValue))
|
|
||||||
return guessValue;
|
|
||||||
|
|
||||||
var loweredTranscript = NormalizeGuessToken(transcript);
|
|
||||||
var hintIndex = loweredTranscript switch
|
|
||||||
{
|
|
||||||
"1" or "one" or "first" => 0,
|
|
||||||
"2" or "two" or "second" => 1,
|
|
||||||
"3" or "three" or "third" => 2,
|
|
||||||
_ => -1
|
|
||||||
};
|
|
||||||
|
|
||||||
if (hintIndex >= 0 && hintIndex < listenAsrHints.Count) return listenAsrHints[hintIndex];
|
|
||||||
|
|
||||||
var fuzzyHintMatch = FindClosestHint(loweredTranscript, listenAsrHints);
|
|
||||||
return !string.IsNullOrWhiteSpace(fuzzyHintMatch) ? fuzzyHintMatch : transcript;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user