I'm trying to program an experiment with the JavaScript package JSPsych. The MWE of my experiment is supposed to do the following: The participant enters a letter in a survey-text trial and in the following html-response trial, this letter is supposed to be presented to the participant as a stimulus.
My problem is that I can't find a way to access the input of the participant in the survey-text trial. My program structure follows the reaction time tutorial on the JSPsych website: The trials are being created one after another and pushed into a timeline array which is being initiated at the very end of the code. What that means is that at the time the trial is being defined the user has not input anything yet.
My MLE code can be found below. While running the experiment in a browser I am able to access the data from the survey-text trial with JSON.parse(jsPsych.data.getLastTrialData().select('responses').values).favorite. However, in the code below this produces the following error: SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data, because (I strongly presume) there is no last trial at the time the code is being compiled.
let letter_display, letter_survey, test_procedure, timeline;
timeline = [];
letter_survey = {
type: "survey-text",
questions: [
{prompt: "What is your favorite letter?", name:"favorite"}
],
}
timeline.push(letter_survey);
letter_display = {
type: 'html-keyboard-response',
stimulus: jsPsych.timelineVariable('stimulus'),
};
test_procedure = {
timeline: [letter_display],
timeline_variables: [{type:'html-keyboard-response', stimulus: JSON.parse(jsPsych.data.getLastTrialData().select('responses').values).favorite}]
};
timeline.push(test_procedure);
jsPsych.init({
timeline: timeline
})
I have found a solution. The part of the code where a value is assigned to the letter_display variable has to be changed as follows:
letter_display = {
type: 'html-keyboard-response',
stimulus: JSON.parse(jsPsych.data.getLastTrialData().select('responses').values).favorite
};
timeline.push(letter_display);
All code relating to the test_procedure variable can be scraped.
I.e. I got this to work for a "flat" timeline, but not a nested one. If anyone has a nested timeline solution, I would appreciate if they posted it as an answer here.
As a side note: Using JSON.parse(jsPsych.data.get().filter( {trial_type: 'survey-text'} ).select('responses').values).favorite generalizes to cases where the user input is not from the last trial.
Let me add another way
The on_start of the trial also works! It can change the stimulus or anything parameters of the trial based on the last trial's repsonse.
letter_display = {
type: 'html-keyboard-response',
stimulus:''
on_start:function(trial){
trial.stimulus =jsPsych.data.getLastTrialData().select('responses').values.favorite
}
};
timeline.push(letter_display);
(if you do not assign the stimulus before the on_start, it can work, but with error message in console)
Related
I am going to do live data streaming on ag-grid datatable, so I used DeltaRowData for gridOptions and added getRowNodeId method as well which return unique value 'id'.
After all, I got a live update result on my grid table within some period I set, but some rows are duplicated so I can notice total count is a bit increased each time it loads updated data. The question title is warning message from browser console, I got bunch of these messages with different id number. Actually it is supposed not to do this from below docs. This is supposed to detect dups and smartly added new ones if not exist. Ofc, there are several ways to get refreshed data live, but I chose this one, since it says it helps to persist grid info like selected rows, current position of scroll on the grid etc. I am using vanilla js, not going to use any frameworks.
How do I make live data updated periodically without changing any current grid stuff? There is no error on the code, so do not try to speak about any bug. Maybe I am wrong with current implementation, Anyway, I want to know the idea or hear any implementation experience on this.
let gridOptions = {
....
deltaRowDataMode: true,
getRowNodeId = (data) => {
return data.id; // return the property you want set as the id.
}
}
fetch(loadUrl).then((res) => {
return res.json()
}).then((data) => {
gridOptions.api.setRowData(data);
})
...
If you get:
duplicated node warning
it means your getRowNodeId() has 1 value for 2 different rows.
here is part from source:
if (this.allNodesMap[node.id]) {
console.warn("ag-grid: duplicate node id '" + node.id + "' detected from getRowNodeId callback, this could cause issues in your grid.");
}
so try to check your data again.
if u 100% sure there is an error not related with your data - cut oof the private data, create a plinkr/stackblitz examples to reproduce your issue and then it would be simpler to check and help you.
I've created a very simple workflow task for a cloud based YouTrack instance. The idea is to prevent (stop workflow) deletion of issues (we'd prefer to keep all issues, even if they were submitted by mistake). The code is provided below.
var entities = require('#jetbrains/youtrack-scripting-api/entities');
var workflow = require('#jetbrains/youtrack-scripting-api/workflow');
exports.rule = entities.Issue.onChange({
// TODO: give the rule a human-readable title
title: 'When-issue-is-deleted',
guard: function(ctx) {
return ctx.issue.becomesRemoved;
},
action: function(ctx) {
workflow.check(false, 'Do not remove issues, please');
}
});
Though I believe it should work, when I tried to remove a new just created issue I received no error messages, and the issue was removed.
I'd recommend an easier way - just disable 'Delete issue' permission for the respective roles (https://www.jetbrains.com/help/youtrack/standalone/Create-and-Edit-Roles.html#editing_existing_roles) and users with these roles will not be able to delete issues.
As for becomesRemoved property which doesn't work properly - this is a known issue, please follow this ticket to receive further updates on it: https://youtrack.jetbrains.com/issue/JT-29303.
Just in case someone else stumbles upon this issue (quoting https://youtrack.jetbrains.com/issue/JT-55220)
To make your onChange rule triggered when an issue becomes removed, you'll need to specify the runOn attribute in the rule's declaration.
runOn: {
change: false,
removal: true
}
I'm needing to create drop ship purchase orders against sales orders within NetSuite that already exist and have one or more drop ship POs created against it. Now, normally through the UI you can just click the "Drop Ship" link on an item line and there you go, but this is being done programmatically with SuiteScript. I thought I had this figured out years ago, but it was years ago, this hasn't come up since, and I can no longer remember what files I may have been working on at the time.
The system won't allow reverting the order to a "Pending Approval" status, so I can't just change statuses around to force the system to create the new POs. I've also tried the following to no success:
soRecord.setCurrentLineItemValue("item", "createpo", "DropShip");
soRecord.setCurrentLineItemValue("item", "povendor", vendorId);
Nothing happens aside from adding the new item lines to the sales order. I've also tried creating a PO with the appropriaate vendor and attaching it to the item line on the sales order with the following, but it also has no effect:
soRecord.setCurrentLineItemValue("item", "createdpo", poId);
Is there something I'm missing? Or have I been embarking on a fool's errand the entire time?
Those fields are read only. This is what I used
var po = nlapiCreateRecord('purchaseorder', {recordmode:"dynamic", soid:<internal id of salesorder>,poentity:<preferred vendor of item>});
We had an issue where our auto-drop ship POs stopped generating on SO creation. In an afterSubmit UE deployed to SOs, gather an array of vendors on the item lines and then filter to remove duplicates. Then add this logic inside of a for-loop where i < length of filtered vendor array:
var createDSPO = record.create({
type: record.Type.PURCHASE_ORDER,
defaultValues: {
soid: <SO internal id>,
shipgroup: 1,
dropship: true,
custid: <SO customer internal ID>,
entity: poVendorArray[i],
poentity: poVendorArray[i]
}
});
createDSPO.save();
FYI, if you inspect the "Drop Ship" link on the SO record, you'll see why I did this. You may be able to figure out another way to do this.
I have a script to create contacts in my database from the contents of my Google Sheet. It first verifies the contact doesn't exist in my database, then adds the contact. I have thousands of contacts, so to reduce the number of contacts in the existing contacts cache, I filter my contact list by state.
var leadsCache = [];
function createContact(leads){
var leadState = '';
for(var i=0; i<leads.length; i++){
if(leads[i].state != leadState){
leadState = leads[i].state;
populateLeadsCache(leadState);
}
var existingLead = leadsCache[leads[i].email];
if(existingLead === undefined){
var leadId = createNewLead(leads[i]);
}
}
}
This works as expected, until I get to a lead with a new state. The code hangs here:
leadState = leads[i].state;
I don't get an error message. I can set the var to empty like this: leadState = '', but I cannot set the value to something else.
In stepping through the code, I can see that leads[i].state has a new string value.
Why can't I change the value? What is the best way to accomplish my desired results?
UPDATE
I wish there was a better error reporting system for Apps Script. Turns out I had an issue in populateLeadsCache (continuous loop) but the system appeared stuck on leadState = leads[i].state;.
Anyone know how to improve the error reporting in Apps Script?
I am answering the question so it can be closed, but leaving the question here in case someone else has a similar issue that isn't really the issue.
Apps Script does not have robust error reporting tools and the debugger failed to highlight the true issue in another part of the code.
When getting a timeout message in Apps Script be aware that it may not have anything to do with where the code appears to break.
For me, the next line of code populateLeadsCache had an issue if the selected state had too many contacts, which resulted in a continuous loop.
I've been trying to do Meteor's leaderboard example, and I'm stuck at the second exercise, resetting the scores. So far, the furthest I've got is this:
// On server startup, create some players if the database is empty.
if (Meteor.isServer) {
Meteor.startup(function () {
if (Players.find().count() === 0) {
var names = ["Ada Lovelace",
"Grace Hopper",
"Marie Curie",
"Carl Friedrich Gauss",
"Nikola Tesla",
"Claude Shannon"];
for (var i = 0; i < names.length; i++)
Players.insert({name: names[i]}, {score: Math.floor(Random.fraction()*10)*5});
}
});
Meteor.methods({
whymanwhy: function(){
Players.update({},{score: Math.floor(Random.fraction()*10)*5});
},
}
)};
And then to use the whymanwhy method I have a section like this in if(Meteor.isClient)
Template.leaderboard.events({
'click input#resetscore': function(){Meteor.call("whymanwhy"); }
});
The problem with this is that {} is supposed to select all the documents in MongoDB collection, but instead it creates a new blank scientist with a random score. Why? {} is supposed to select everything. I tried "_id" : { $exists : true }, but it's a kludge, I think. Plus it behaved the same as {}.
Is there a more elegant way to do this? The meteor webpage says:
Make a button that resets everyone's score to a random number. (There
is already code to do this in the server startup code. Can you factor
some of this code out and have it run on both the client and the
server?)
Well, to run this on the client first, instead of using a method to the server and having the results pushed back to the client, I would need to explicitly specify the _ids of each document in the collection, otherwise I will run into the "Error: Not permitted. Untrusted code may only update documents by ID. [403]". But how can I get that? Or should I just make it easy and use collection.allow()? Or is that the only way?
I think you are missing two things:
you need to pass the option, {multi: true}, to update or it will only ever change one record.
if you only want to change some fields of a document you need to use $set. Otherwise update assumes you are providing the complete new document you want and replaces the original.
So I think the correct function is:
Players.update({},{$set: {score: Math.floor(Random.fraction()*10)*5}}, {multi:true});
The documentation on this is pretty thorough.