/* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ using Meta.WitAi.Data.Entities; using Meta.WitAi.Data.Intents; using Meta.WitAi.Json; using UnityEngine; namespace Meta.WitAi { public static class WitResultUtilities { // Keys public const string WIT_KEY_TRANSCRIPTION = "text"; public const string WIT_KEY_INTENTS = "intents"; public const string WIT_KEY_ENTITIES = "entities"; public const string WIT_KEY_TRAITS = "traits"; public const string WIT_KEY_FINAL = "is_final"; #region Base Response methods /// /// Get the transcription from a wit response node /// public static string GetTranscription(this WitResponseNode witResponse) => null != witResponse && witResponse.AsObject != null && witResponse.AsObject.HasChild(WIT_KEY_TRANSCRIPTION) ? witResponse[WIT_KEY_TRANSCRIPTION].Value : string.Empty; /// /// Get whether this response is a 'final' response /// public static bool HasResponse(this WitResponseNode witResponse) => null != witResponse && witResponse.AsObject != null && (witResponse.AsObject.HasChild(WIT_KEY_INTENTS) || witResponse.AsObject.HasChild(WIT_KEY_ENTITIES) || witResponse.AsObject.HasChild(WIT_KEY_TRAITS)); /// /// Get whether this response is a 'final' response /// public static bool GetIsFinal(this WitResponseNode witResponse) => null != witResponse && witResponse.AsObject != null && witResponse.AsObject.HasChild(WIT_KEY_FINAL) && witResponse[WIT_KEY_FINAL].AsBool; #endregion #region Entity methods /// /// Converts wit response node into a wit entity /// public static WitEntityData AsWitEntity(this WitResponseNode witResponse) => new WitEntityData(witResponse); /// /// Converts wit response node into a float entity /// public static WitEntityFloatData AsWitFloatEntity(this WitResponseNode witResponse) => new WitEntityFloatData(witResponse); /// /// Converts wit response node into an int entity /// public static WitEntityIntData AsWitIntEntity(this WitResponseNode witResponse) => new WitEntityIntData(witResponse); /// /// Gets the string value of the first entity /// /// /// /// public static string GetFirstEntityValue(this WitResponseNode witResponse, string name) { return witResponse?[WIT_KEY_ENTITIES]?[name]?[0]?["value"]?.Value; } /// /// Gets a collection of string value containing the selected value from /// each entity in the response. /// /// /// /// public static string[] GetAllEntityValues(this WitResponseNode witResponse, string name) { var values = new string[witResponse?[WIT_KEY_ENTITIES]?[name]?.Count ?? 0]; for (var i = 0; i < witResponse?[WIT_KEY_ENTITIES]?[name]?.Count; i++) { values[i] = witResponse?[WIT_KEY_ENTITIES]?[name]?[i]?["value"]?.Value; } return values; } /// /// Gets the first entity as a WitResponseNode /// /// /// /// public static WitResponseNode GetFirstEntity(this WitResponseNode witResponse, string name) { return witResponse?[WIT_KEY_ENTITIES]?[name][0]; } /// /// Gets the first entity with the given name as string data /// /// /// The entity name typically something like name:name /// public static WitEntityData GetFirstWitEntity(this WitResponseNode witResponse, string name) { var array = witResponse?[WIT_KEY_ENTITIES]?[name].AsArray; return array?.Count > 0 ? array[0].AsWitEntity() : null; } /// /// Gets The first entity with the given name as int data /// /// /// The entity name typically something like name:name /// public static WitEntityIntData GetFirstWitIntEntity(this WitResponseNode witResponse, string name) { var array = witResponse?[WIT_KEY_ENTITIES]?[name].AsArray; return array?.Count > 0 ? array[0].AsWitIntEntity() : null; } /// /// Gets The first entity with the given name as int data /// /// /// The entity name typically something like name:name /// public static int GetFirstWitIntValue(this WitResponseNode witResponse, string name, int defaultValue) { var array = witResponse?[WIT_KEY_ENTITIES]?[name].AsArray; if (null == array || array.Count == 0) return defaultValue; return array[0].AsWitIntEntity().value; } /// /// Gets the first entity with the given name as float data /// /// /// The entity name typically something like name:name /// public static WitEntityFloatData GetFirstWitFloatEntity(this WitResponseNode witResponse, string name) { var array = witResponse?[WIT_KEY_ENTITIES]?[name].AsArray; return array?.Count > 0 ? array[0].AsWitFloatEntity() : null; } /// /// Gets The first entity with the given name as int data /// /// /// The entity name typically something like name:name /// public static float GetFirstWitFloatValue(this WitResponseNode witResponse, string name, float defaultValue) { var array = witResponse?[WIT_KEY_ENTITIES]?[name].AsArray; if (null == array || array.Count == 0) return defaultValue; return array[0].AsWitFloatEntity().value; } /// /// Gets all entities in the given response /// /// The root response node of an VoiceService.events.OnResponse event /// public static WitEntityData[] GetEntities(this WitResponseNode witResponse, string name) { var entityJsonArray = witResponse?[WIT_KEY_ENTITIES]?[name].AsArray; var entities = new WitEntityData[entityJsonArray?.Count ?? 0]; for (int i = 0; i < entities.Length; i++) { entities[i] = entityJsonArray[i].AsWitEntity(); } return entities; } /// /// Returns the total number of entities /// /// /// public static int EntityCount(this WitResponseNode response) { return response?[WIT_KEY_ENTITIES]?.AsArray?.Count ?? 0; } /// /// Gets all float entity values in the given response with the specified entity name /// /// The root response node of an VoiceService.events.OnResponse event /// The entity name typically something like name:name /// public static WitEntityFloatData[] GetFloatEntities(this WitResponseNode witResponse, string name) { var entityJsonArray = witResponse?[WIT_KEY_ENTITIES]?[name].AsArray; var entities = new WitEntityFloatData[entityJsonArray?.Count ?? 0]; for (int i = 0; i < entities.Length; i++) { entities[i] = entityJsonArray[i].AsWitFloatEntity(); } return entities; } /// /// Gets all int entity values in the given response with the specified entity name /// /// The root response node of an VoiceService.events.OnResponse event /// The entity name typically something like name:name /// public static WitEntityIntData[] GetIntEntities(this WitResponseNode witResponse, string name) { var entityJsonArray = witResponse?[WIT_KEY_ENTITIES]?[name].AsArray; var entities = new WitEntityIntData[entityJsonArray?.Count ?? 0]; for (int i = 0; i < entities.Length; i++) { entities[i] = entityJsonArray[i].AsWitIntEntity(); } return entities; } #endregion #region Intent methods /// /// Converts wit response node into wit intent data /// public static WitIntentData AsWitIntent(this WitResponseNode witResponse) => new WitIntentData(witResponse); /// /// Gets the first intent's name /// /// /// public static string GetIntentName(this WitResponseNode witResponse) { return witResponse == null || !witResponse.AsObject.HasChild(WIT_KEY_INTENTS) ? null : witResponse[WIT_KEY_INTENTS][0]?["name"]?.Value; } /// /// Gets the first intent node /// /// /// public static WitResponseNode GetFirstIntent(this WitResponseNode witResponse) { return witResponse == null || !witResponse.AsObject.HasChild(WIT_KEY_INTENTS) ? null : witResponse[WIT_KEY_INTENTS][0]; } /// /// Gets the first set of intent data /// /// /// WitIntentData or null if no intents are found public static WitIntentData GetFirstIntentData(this WitResponseNode witResponse) { var array = witResponse == null || !witResponse.AsObject.HasChild(WIT_KEY_INTENTS) ? null : witResponse[WIT_KEY_INTENTS]?.AsArray; return array?.Count > 0 ? array[0].AsWitIntent() : null; } /// /// Gets all intents in the given response /// /// The root response node of an VoiceService.events.OnResponse event /// public static WitIntentData[] GetIntents(this WitResponseNode witResponse) { var intentResponseArray = witResponse == null || !witResponse.AsObject.HasChild(WIT_KEY_INTENTS) ? null : witResponse[WIT_KEY_INTENTS]?.AsArray; var intents = new WitIntentData[intentResponseArray?.Count ?? 0]; for (int i = 0; i < intents.Length; i++) { intents[i] = intentResponseArray[i].AsWitIntent(); } return intents; } #endregion #region Misc. Helper Methods public static string GetPathValue(this WitResponseNode response, string path) { string[] nodes = path.Trim('.').Split('.'); var node = response; foreach (var nodeName in nodes) { string[] arrayElements = SplitArrays(nodeName); node = node[arrayElements[0]]; for (int i = 1; i < arrayElements.Length; i++) { node = node[int.Parse(arrayElements[i])]; } } return node.Value; } public static void SetString(this WitResponseNode response, string path, string value) { string[] nodes = path.Trim('.').Split('.'); var node = response; int nodeIndex; for(nodeIndex = 0; nodeIndex < nodes.Length - 1; nodeIndex++) { var nodeName = nodes[nodeIndex]; string[] arrayElements = SplitArrays(nodeName); node = node[arrayElements[0]]; for (int i = 1; i < arrayElements.Length; i++) { node = node[int.Parse(arrayElements[i])]; } } node[nodes[nodeIndex]] = value; } public static void RemovePath(this WitResponseNode response, string path) { string[] nodes = path.Trim('.').Split('.'); var node = response; WitResponseNode parent = null; foreach (var nodeName in nodes) { string[] arrayElements = SplitArrays(nodeName); parent = node; node = node[arrayElements[0]]; for (int i = 1; i < arrayElements.Length; i++) { node = node[int.Parse(arrayElements[i])]; } } if (null != parent) parent.Remove(node); } public static WitResponseReference GetWitResponseReference(string path) { string[] nodes = path.Trim('.').Split('.'); var rootNode = new WitResponseReference() { path = path }; var node = rootNode; foreach (var nodeName in nodes) { string[] arrayElements = SplitArrays(nodeName); var childObject = new ObjectNodeReference() { path = path }; childObject.key = arrayElements[0]; node.child = childObject; node = childObject; for (int i = 1; i < arrayElements.Length; i++) { var childIndex = new ArrayNodeReference() { path = path }; childIndex.index = int.Parse(arrayElements[i]); node.child = childIndex; node = childIndex; } } return rootNode; } public static string GetCodeFromPath(string path) { string[] nodes = path.Trim('.').Split('.'); string code = "witResponse"; foreach (var nodeName in nodes) { string[] arrayElements = SplitArrays(nodeName); code += $"[\"{arrayElements[0]}\"]"; for (int i = 1; i < arrayElements.Length; i++) { code += $"[{arrayElements[i]}]"; } } code += ".Value"; return code; } private static string[] SplitArrays(string nodeName) { var nodes = nodeName.Split('['); for (int i = 0; i < nodes.Length; i++) { nodes[i] = nodes[i].Trim(']'); } return nodes; } #endregion #region Trait Methods /// /// Gets the string value of the first trait /// /// /// /// public static string GetTraitValue(this WitResponseNode witResponse, string name) { return witResponse?[WIT_KEY_TRAITS]?[name]?[0]?["value"]?.Value; } #endregion } #region WitResponseReference Child Classes public class WitResponseReference { public WitResponseReference child; public string path; public virtual string GetStringValue(WitResponseNode response) { return child.GetStringValue(response); } public virtual int GetIntValue(WitResponseNode response) { return child.GetIntValue(response); } public virtual float GetFloatValue(WitResponseNode response) { return child.GetFloatValue(response); } } public class ArrayNodeReference : WitResponseReference { public int index; public override string GetStringValue(WitResponseNode response) { if (null != child) { return child.GetStringValue(response[index]); } return response[index].Value; } public override int GetIntValue(WitResponseNode response) { if (null != child) { return child.GetIntValue(response[index]); } return response[index].AsInt; } public override float GetFloatValue(WitResponseNode response) { if (null != child) { return child.GetFloatValue(response[index]); } return response[index].AsInt; } } public class ObjectNodeReference : WitResponseReference { public string key; public override string GetStringValue(WitResponseNode response) { if (null != child && null != response?[key]) { return child.GetStringValue(response[key]); } return response?[key]?.Value; } public override int GetIntValue(WitResponseNode response) { if (null != child) { return child.GetIntValue(response[key]); } return response[key].AsInt; } public override float GetFloatValue(WitResponseNode response) { if (null != child) { return child.GetFloatValue(response[key]); } return response[key].AsFloat; } } #endregion }