I have a list of values each having another KEY value corresponding to it, when i present this list to user, user has to select a value and agent has to call an external api with selected value's KEY. how can i achieve this in dialogflow?
I tried to send the entire key value pair in the context and access it in the next intent but for some reason when i set a list(array) to context parameters dialogflow simply ignoring the fulfillment response.
What is happening here and is there any good way to achieve this? I am trying to develop a food ordering chatbot where the category of items in menu is presented and list items in that menu will fetched when user selects a category, this menu is not static thats why i am using api calls to get the dynamic menu.
function newOrder(agent)
{
var categories = []
var cat_parameters = {}
var catarray = []
const conv = agent.conv();
//conv.ask('sure, select a category to order');
agent.add('select a category to order');
return getAllCategories().then((result)=>{
for(let i=0; i< result.restuarantMenuList.length; i++)
{
try{
var name = result.restuarantMenuList[i].Name;
var catid = result.restuarantMenuList[i].Id;
categories.push(name)
//categories.name = catid
cat_parameters['id'] = catid;
cat_parameters['name'] = name
catarray.push(cat_parameters)
}catch(ex)
{
agent.add('trouble getting the list please try again later')
}
}
agent.context.set({
name: 'categorynames',
lifespan: 5,
parameters: catarray, // if i omit this line, the reponse is the fultillment response with categories names, if i keep this line the reponse is fetching from default static console one.
})
return agent.add('\n'+categories.toString())
})
function selectedCategory(agent)
{
//agent.add('category items should be fetched and displayed here');
var cat = agent.parameters.category
const categories = agent.context.get('categorynames')
const cat_ob = categories.parameters.cat_parameters
// use the key in the catarray with the parameter cat to call the external API
agent.add('you have selected '+ cat );
}
}
The primary issue is that the context parameters must be an object, it cannot be an array.
So when you save it, you can do something like
parameters: {
"cat_parameters": catarray
}
and when you deal with it when you get the reply, you can get the array back with
let catarray = categories.parameters.cat_parameters;
(There are some other syntax and scoping issues with your code, but this seems like it is the data availability issue you're having.)
I am trying a test a use case where I have taken two assets: a car and parts. I want to link the car with different instances of parts using a transaction. My model and js files are below :
namespace org.sample.test
asset Part identified by partId {
o String partId
o String partName
o String partManufacturer
}
asset Car identified by Vin {
o String Vin
--> Part part optional
o String modelNumber
}
transaction MakeCar{
o String carid
o String carmodel
o String[] PartId
}
/**
* Sample transaction processor function.
* #param {org.sample.test.MakeCar} tx The sample transaction instance.
* #transaction
*/
async function makecar(tx) { // eslint-disable-line no-unused-vars
var factory = getFactory();
var vehicle = factory.newResource('org.sample.test','Car',tx.carid);
vehicle.modelNumber = tx.carmodel;
var part = factory.newRelationship('org.sample.test','Part',tx.PartId);
vehicle.part = part;
const assetRegistry = await getAssetRegistry('org.sample.test.Car');
await assetRegistry.add(vehicle);
// Update the asset in the asset registry.
}
I also tried first creating the asset using the getfactory then creating relations by traversing partIds one by one using array but then as my Car asset is not created yet its throwing error.
I updated my transaction fucntion :
async function makecar(tx) { // eslint-disable-line no-unused-vars
var factory = getFactory();
var part;
var vehicle = factory.newResource('org.sample.test','Car',tx.carid);
vehicle.modelNumber = tx.carmodel;
var i=0;
while (i<tx.PartId.length)
{
part = factory.newRelationship('org.sample.test','Part',tx.PartId[i]);
vehicle.part = part;
i++;
}
assetRegistry = await getAssetRegistry('org.sample.test.Car');
await assetRegistry.add(vehicle);
}
Now its giving error : t: Instance org.sample.test.Car#OOOO has property part with type org.sample.test.Part that is not derived from org.sample.test.Part[]
the problem is this line:
var part = factory.newRelationship('org.sample.test','Part',tx.PartId);
it should be [something like]:
var part = factory.newRelationship('org.example.trading','Part',tx.PartId[0]); // 1st element of an array
its because you've defined tx.PartId as an array of relationships in your transaction definition, so you need to access the relevant element.
At this point, I'm not sure how you want to move forward, but your Car (vehicle) asset has an optional one to one relationship with Part (part Id) which is the optional field in your model. Perhaps it needs to be an array of relationships ? -> Part[] part optional But replacing the line above, will at least have it working, in its present form. An example of using an array of relationships is shown in the answer in this SO: -> Creating new participant and adding array of assets by reference to it (in particular :shares array in the model there)
I'm trying to write a little complexer logic in the condition of an ACL Rule as always the p.getIdentifier() == r.getIdentifier(), because in my fault it isn't possible.
These are my models:
participant Customer identified by customerID {
o String customerID
o String name
...
}
asset A identified by aID {
o String aID
--> Customer customer
}
asset B identified by bID {
o String bID
--> A a
}
Now I want to give the Customer access to see all B assets, but only where the relationship to A references to an asset, which have a relatinship to the actual participant of Customer, who is "logged in".
Summarized logic: From asset B to A, and then from A to Customer.
So in this case I can't compare the identifiers of Customer and B directly and have to go over A. Therefore I wanted to evaulate the access with a function which is called in the script.js file:
rule CustomerAccessCustomer {
description: "The customer should see all B assets, but only when he have a relationship in asset A "
participant(p): "org.xxx.test.participant.Customer"
operation: READ
resource(r): "org.xxx.test.asset.B"
condition: (evaluateAccess(p,r))
action: ALLOW
}
Here is the function of the script.js:
async function evaluateAccess(p,r) {
try {
const bRegistry = await getAssetRegistry('org.xxx.test.asset.B');
const b = await bRegistry.get(r.getIdentifier());
const aRegistry = await getAssetRegistry('org.xxx.test.asset.A');
const a = await aRegistry.get(b.a.getIdentifier());
if (p.getIdentifier() === a.customer.getIdentifier()) {
return true;
}
} catch (error) {
console.log(error);
}
}
But I get an error Error: The runtime API is not available.
Do I think the wrong way, isn't it possible to evaluate access with a function?
How did you handle access rule if you can't just compare the identifiers?
you should just be able to do:
rule CustomerAccessCustomer {
description: "The customer should see all B assets, but only when he have a relationship in asset A "
participant(p): "org.xxx.test.participant.Customer"
operation: READ
resource(r): "org.xxx.test.asset.B"
condition: ( (p.getIdentifier() === r.a.customer.getIdentifier())
action: ALLOW
}
but p would also need READ access already to be able to 'read' Asset resource 'A' (to check the identifier etc) in the first place :-)
The customer should be participant not asset:
participant Customer identified by customerID {
o String customerID
o String name
}
function Exchange(exchange){
// We do the actual exchange here:
// We first need to get both actual nodes:
var nodeIdFrom=exchange.nodeIdFrom;
var quantity =exchange.quantity;
var price = exchange.price;
var nodeIdTo =exchange.nodeIdTo;
return getParticipantRegistry('org.acme.mynetwork.Node')
.then(function(ParticipantRegistry){
ParticipantRegistry.get(nodeIdFrom)
.then(function(Participant){
Participant.Need=Participant.Need+quantity;
Participant.Balance_account=Participant.Balance_account+quantity*price;
return ParticipantRegistry.update(Participant);
});
});
I'm trying to execute a transaction defined as:
transaction Exchange{
o String nodeIdFrom
o String nodeIdTo
o Double quantity
o Double Price
}
To execute a transaction (we take money somewhere and put it somewhere else). With only the ids of the nodes as a parameter.
But right now that function does not work, you can execute it on the playground but my node is not modified.
Is it possible to apply a transaction without giving node as Node (node is a Participant).
it should work - here's an example (Using a fictitious sample 'Trader' Network and like you, I have defined 'qty' as a 'Double' in the Transaction model definition itself) of updating an Asset by a specific identifier (you're doing something similar - Participant by ID) and then - updating the asset's quantity using the Promises chain below. Suggest to use console.log() for outputs too when debugging.
So - given Transaction model:
transaction TraderById {
o String tradeId
o String tradingSymbol
o Double qty
}
and an Asset modeled as:
asset Commodity identified by tradingSymbol {
o String tradingSymbol
o String description
o String mainExchange
o Double quantity
--> Trader owner
}
you can update the Asset quantity ('quantity') as follows:
/**
*
* #param {org.acme.trading.TraderById} tradeById - the trade to be processed
* #transaction
*/
function TradeById(tradeById){
var commodityRegistry;
return getAssetRegistry('org.acme.trading.Commodity')
.then(function(registry){
commodityRegistry=registry;
return commodityRegistry.get(tradeById.tradingSymbol);
})
.then(function(result){
result.quantity-=tradeById.qty;
return commodityRegistry.update(result);
});
}
I am aware of how to create getters and setters for properties whose names one already knows, by doing something like this:
// A trivial example:
function MyObject(val){
this.count = 0;
this.value = val;
}
MyObject.prototype = {
get value(){
return this.count < 2 ? "Go away" : this._value;
},
set value(val){
this._value = val + (++this.count);
}
};
var a = new MyObject('foo');
alert(a.value); // --> "Go away"
a.value = 'bar';
alert(a.value); // --> "bar2"
Now, my question is, is it possible to define sort of catch-all getters and setters like these? I.e., create getters and setters for any property name which isn't already defined.
The concept is possible in PHP using the __get() and __set() magic methods (see the PHP documentation for information on these), so I'm really asking is there a JavaScript equivalent to these?
Needless to say, I'd ideally like a solution that is cross-browser compatible.
This changed as of the ES2015 (aka "ES6") specification: JavaScript now has proxies. Proxies let you create objects that are true proxies for (facades on) other objects. Here's a simple example that turns any property values that are strings to all caps on retrieval, and returns "missing" instead of undefined for a property that doesn't exist:
"use strict";
if (typeof Proxy == "undefined") {
throw new Error("This browser doesn't support Proxy");
}
let original = {
example: "value",
};
let proxy = new Proxy(original, {
get(target, name, receiver) {
if (Reflect.has(target, name)) {
let rv = Reflect.get(target, name, receiver);
if (typeof rv === "string") {
rv = rv.toUpperCase();
}
return rv;
}
return "missing";
}
});
console.log(`original.example = ${original.example}`); // "original.example = value"
console.log(`proxy.example = ${proxy.example}`); // "proxy.example = VALUE"
console.log(`proxy.unknown = ${proxy.unknown}`); // "proxy.unknown = missing"
original.example = "updated";
console.log(`original.example = ${original.example}`); // "original.example = updated"
console.log(`proxy.example = ${proxy.example}`); // "proxy.example = UPDATED"
Operations you don't override have their default behavior. In the above, all we override is get, but there's a whole list of operations you can hook into.
In the get handler function's arguments list:
target is the object being proxied (original, in our case).
name is (of course) the name of the property being retrieved, which is usually a string but could also be a Symbol.
receiver is the object that should be used as this in the getter function if the property is an accessor rather than a data property. In the normal case this is the proxy or something that inherits from it, but it can be anything since the trap may be triggered by Reflect.get.
This lets you create an object with the catch-all getter and setter feature you want:
"use strict";
if (typeof Proxy == "undefined") {
throw new Error("This browser doesn't support Proxy");
}
let obj = new Proxy({}, {
get(target, name, receiver) {
if (!Reflect.has(target, name)) {
console.log("Getting non-existent property '" + name + "'");
return undefined;
}
return Reflect.get(target, name, receiver);
},
set(target, name, value, receiver) {
if (!Reflect.has(target, name)) {
console.log(`Setting non-existent property '${name}', initial value: ${value}`);
}
return Reflect.set(target, name, value, receiver);
}
});
console.log(`[before] obj.example = ${obj.example}`);
obj.example = "value";
console.log(`[after] obj.example = ${obj.example}`);
The output of the above is:
Getting non-existent property 'example'
[before] obj.example = undefined
Setting non-existent property 'example', initial value: value
[after] obj.example = value
Note how we get the "non-existent" message when we try to retrieve example when it doesn't yet exist, and again when we create it, but not after that.
Answer from 2011 (obsoleted by the above, still relevant to environments limited to ES5 features like Internet Explorer):
No, JavaScript doesn't have a catch-all property feature. The accessor syntax you're using is covered in Section 11.1.5 of the spec, and doesn't offer any wildcard or something like that.
You could, of course, implement a function to do it, but I'm guessing you probably don't want to use f = obj.prop("example"); rather than f = obj.example; and obj.prop("example", value); rather than obj.example = value; (which would be necessary for the function to handle unknown properties).
FWIW, the getter function (I didn't bother with setter logic) would look something like this:
MyObject.prototype.prop = function(propName) {
if (propName in this) {
// This object or its prototype already has this property,
// return the existing value.
return this[propName];
}
// ...Catch-all, deal with undefined property here...
};
But again, I can't imagine you'd really want to do that, because of how it changes how you use the object.
Preface:
T.J. Crowder's answer mentions a Proxy, which will be needed for a catch-all getter/setter for properties which don't exist, as the OP was asking for. Depending on what behavior is actually wanted with dynamic getters/setters, a Proxy may not actually be necessary though; or, potentially, you may want to use a combination of a Proxy with what I'll show you below.
(P.S. I have experimented with Proxy thoroughly in Firefox on Linux recently and have found it to be very capable, but also somewhat confusing/difficult to work with and get right. More importantly, I have also found it to be quite slow (at least in relation to how optimized JavaScript tends to be nowadays) - I'm talking in the realm of deca-multiples slower.)
To implement dynamically created getters and setters specifically, you can use Object.defineProperty() or Object.defineProperties(). This is also quite fast.
The gist is that you can define a getter and/or setter on an object like so:
let obj = {};
let val = 0;
Object.defineProperty(obj, 'prop', { //<- This object is called a "property descriptor".
//Alternatively, use: `get() {}`
get: function() {
return val;
},
//Alternatively, use: `set(newValue) {}`
set: function(newValue) {
val = newValue;
}
});
//Calls the getter function.
console.log(obj.prop);
let copy = obj.prop;
//Etc.
//Calls the setter function.
obj.prop = 10;
++obj.prop;
//Etc.
Several things to note here:
You cannot use the value property in the property descriptor (not shown above) simultaneously with get and/or set; from the docs:
Property descriptors present in objects come in two main flavors: data descriptors and accessor descriptors. A data descriptor is a property that has a value, which may or may not be writable. An accessor descriptor is a property described by a getter-setter pair of functions. A descriptor must be one of these two flavors; it cannot be both.
Thus, you'll note that I created a val property outside of the Object.defineProperty() call/property descriptor. This is standard behavior.
As per the error here, don't set writable to true in the property descriptor if you use get or set.
You might want to consider setting configurable and enumerable, however, depending on what you're after; from the docs:
configurable
true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.
Defaults to false.
enumerable
true if and only if this property shows up during enumeration of the properties on the corresponding object.
Defaults to false.
On this note, these may also be of interest:
Object.getOwnPropertyNames(obj): gets all properties of an object, even non-enumerable ones (AFAIK this is the only way to do so!).
Object.getOwnPropertyDescriptor(obj, prop): gets the property descriptor of an object, the object that was passed to Object.defineProperty() above.
obj.propertyIsEnumerable(prop);: for an individual property on a specific object instance, call this function on the object instance to determine whether the specific property is enumerable or not.
The following could be an original approach to this problem:
var obj = {
emptyValue: null,
get: function(prop){
if(typeof this[prop] == "undefined")
return this.emptyValue;
else
return this[prop];
},
set: function(prop,value){
this[prop] = value;
}
}
In order to use it the properties should be passed as strings.
So here is an example of how it works:
//To set a property
obj.set('myProperty','myValue');
//To get a property
var myVar = obj.get('myProperty');
Edit:
An improved, more object-oriented approach based on what I proposed is the following:
function MyObject() {
var emptyValue = null;
var obj = {};
this.get = function(prop){
return (typeof obj[prop] == "undefined") ? emptyValue : obj[prop];
};
this.set = function(prop,value){
obj[prop] = value;
};
}
var newObj = new MyObject();
newObj.set('myProperty','MyValue');
alert(newObj.get('myProperty'));
You can see it working here.
I was looking for something and I figured out on my own.
/*
This function takes an object and converts to a proxy object.
It also takes care of proxying nested objectsa and array.
*/
let getProxy = (original) => {
return new Proxy(original, {
get(target, name, receiver) {
let rv = Reflect.get(target, name, receiver);
return rv;
},
set(target, name, value, receiver) {
// Proxies new objects
if(typeof value === "object"){
value = getProxy(value);
}
return Reflect.set(target, name, value, receiver);
}
})
}
let first = {};
let proxy = getProxy(first);
/*
Here are the tests
*/
proxy.name={} // object
proxy.name.first={} // nested object
proxy.name.first.names=[] // nested array
proxy.name.first.names[0]={first:"vetri"} // nested array with an object
/*
Here are the serialised values
*/
console.log(JSON.stringify(first)) // {"name":{"first":{"names":[{"first":"vetri"}]}}}
console.log(JSON.stringify(proxy)) // {"name":{"first":{"names":[{"first":"vetri"}]}}}
var x={}
var propName = 'value'
var get = Function("return this['" + propName + "']")
var set = Function("newValue", "this['" + propName + "'] = newValue")
var handler = { 'get': get, 'set': set, enumerable: true, configurable: true }
Object.defineProperty(x, propName, handler)
this works for me