Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

[HELP...please] Sheet Conversion Sheet Worker

1511054871
Finderski
Pro
Sheet Author
Compendium Curator
So, I have been working on a Sheet Worker to convert fields to new fields to consolidate the Savage Worlds Tabbed sheet.  I have all the static fields working and am now working on the repeating sections.  Because I have multiple repeating sections, I wanted to create a function so I only have to do the code once.  Here's what I came up with: function convertRS (mookSection, wcSection, fieldArray) { console.log("mookSection: " + mookSection); console.log("wcSection: " + wcSection); console.log("fieldArray: " + fieldArray); console.log("Number of Entries in fieldArray: " + fieldArray.length); var mookRS = "repeating_"+mookSection; getSectionIDs(mookRS, function(idArray) { if (idArray.length > 0) { console.log("mookSection IDs: " + idArray); //Create a new row in the wcSection for every row in the mookSection for(var i=0; i < idArray.length; i++) { var newrowid = generateRowID(); console.log("***** New Row ID: "+newrowid+" *****"); var mookRF = "repeating_" + mookSection + "_" + idArray[i] + "_m"; var wcRF = "repeating_" + wcSection + "_" + newrowid + "_"; //For this idArray SectionID value need to get the ATTRS for the entire row and create them for(var r=0; r < fieldArray.length; r++) { console.log("********************"); console.log("** mookRF: "+mookRF+fieldArray[r]); console.log("** wcRF: "+wcRF+fieldArray[r]); console.log("********************"); var getMRF = mookRF+fieldArray[r]; var putWCRF = wcRF+fieldArray[r]; getAttrs([getMRF], function(attr) { console.log("### value to be set ("+getMRF+": " + attr.getMRF); /*setAttrs({ [putWCRF] = attr.[getMRF] });*/ }); } } } else { console.log("<===== "+mookSection+" had no rows =====>") } }); } Everything works fine, except the getAttrs section... The console log reports attr.getMRF as Undefined, but when I use the value of getMRF in the game, it returns the appropriate value.  So, what am I doing wrong with my getAttrs call? Any help is greatly appreciated.
1511059020
Finderski
Pro
Sheet Author
Compendium Curator
So, I updated... console.log("### value to be set ("+getMRF+": " + attr.getMRF); to... console.log("### value to be set ("+getMRF+": " + attr[getMRF]); And that seems to be getting me closer, but...I'm still getting getting things undefined: Not sure why I'm getting 5 instances of repeating_mhindrances_-kyw3bls4survhagyi113_mhindrancedescription as undefined and one instance with the proper value, and not getting any of the other rows/fields (as reported in the first screenshot, there are 3 rows and 2 fields in each row).  All the variables are built correctly when put together (meaning, I can take the fully qualified variables that are output and drop them into the game and get the proper value for each field)...
1511068243
Finderski
Pro
Sheet Author
Compendium Curator
Here's the updated code (changes in bold ): function convertRS (mookSection, wcSection, fieldArray) { console.log("mookSection: " + mookSection); console.log("wcSection: " + wcSection); console.log("fieldArray: " + fieldArray); console.log("Number of Entries in fieldArray: " + fieldArray.length); var mookRS = "repeating_"+mookSection; getSectionIDs(mookRS, function(idArray) { if (idArray.length > 0) { console.log("mookSection IDs: " + idArray); //Create a new row in the wcSection for every row in the mookSection for(var i=0; i < idArray.length; i++) { var newrowid = generateRowID(); console.log("***** New Row ID: "+newrowid+" *****"); var mookRF = "repeating_" + mookSection + "_" + idArray[i] + "_m"; var wcRF = "repeating_" + wcSection + "_" + newrowid + "_"; //For this idArray SectionID value need to get the ATTRS for the entire row and create them for(var r=0; r < fieldArray.length; r++) { console.log("********************"); console.log("** mookRF: "+mookRF+fieldArray[r]); console.log("** wcRF: "+wcRF+fieldArray[r]); console.log("********************"); var getMRF = mookRF+fieldArray[r]; console.log(i+"-"+r+") Current value of getMRF: "+getMRF); var putWCRF = wcRF+fieldArray[r]; getAttrs([getMRF], function(attr) { console.log("### value to be set ("+getMRF+": " + attr[getMRF] ); sattrs = {}; sattrs[putWCRF]=attr[getMRF]; setAttrs(sattrs); }); } } } else { console.log("<===== "+mookSection+" had no rows =====>") } }); } With this, the character sheet is able to create a row in the appropriate repeating field, but it only creates 1 row (when there should be 3), and it only populates the last field of the third 3 row of data....
1511074773
Jakob
Sheet Author
API Scripter
I think the issue you might be running into here is that generateRowID() does not actually create a unique ID; if you run it several times in immediate succession, it will actually create the same ID! The solution is to use a while loop where you can keep executing generateRowID() until it produces an actual new ID. A general remark on the code structure that came to my mind (that will probably impact performance, but not functionality): currently, your code runs getAttrs and setAttrs every time it goes through the inner loop. It may be more economical to get all the attributes you need for one repeating section in one getAttrs call and set them all in one setAttrs call.
1511084396
Finderski
Pro
Sheet Author
Compendium Curator
First—Thanks for reply and help, I really appreciate it. I'm actually getting different row IDs... However, my inner for loop seems to be running the same field every time... As for your other suggestion...I'd actually love to do that, I just don't know how. The problem I'm running into is I want this function to be able to handle all of the repeating sections and most of them have different numbers of rows (I started with this particular repeating section because it only has 2 fields, so I figured I'd tackle an easier one first).  Even with this I can't get it to write all the fields in the single row it actually creates: So, if you can point me in the right direction, I'd love to do a full row at a time if I can.
1511084944
Finderski
Pro
Sheet Author
Compendium Curator
Those images are pretty hard to read...sorry. :( Here's the text (copy/pasted) ***** New Row ID: -KzIcZW1a8qKlEmw8h8R ***** (unknown) ******************** (unknown) ** mookRF: repeating_mhindrances_-kyw36zpzxi6ldec39ro_mhindrance (unknown) ** wcRF: repeating_hindrances_-KzIcZW1a8qKlEmw8h8R_hindrance (unknown) ******************** (unknown) 0-0) Current value of getMRF: repeating_mhindrances_-kyw36zpzxi6ldec39ro_mhindrance (unknown) ******************** (unknown) ** mookRF: repeating_mhindrances_-kyw36zpzxi6ldec39ro_mhindrancedescription (unknown) ** wcRF: repeating_hindrances_-KzIcZW1a8qKlEmw8h8R_hindrancedescription (unknown) ******************** (unknown) 0-1) Current value of getMRF: repeating_mhindrances_-kyw36zpzxi6ldec39ro_mhindrancedescription VM23:694 ### Loop Number: 3 VM23:695 ### value to be set (repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription: undefined (unknown) ***** New Row ID: -KzIcZW1a8qKlEmw8h8S ***** VM23:694 ### Loop Number: 3 (unknown) ******************** VM23:695 ### value to be set (repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription: undefined (unknown) ** mookRF: repeating_mhindrances_-kyw394gx2vxyfm1tvb1_mhindrance (unknown) ** wcRF: repeating_hindrances_-KzIcZW1a8qKlEmw8h8S_hindrance (unknown) ******************** (unknown) 1-0) Current value of getMRF: repeating_mhindrances_-kyw394gx2vxyfm1tvb1_mhindrance (unknown) ******************** (unknown) ** mookRF: repeating_mhindrances_-kyw394gx2vxyfm1tvb1_mhindrancedescription VM23:694 ### Loop Number: 3 (unknown) ** wcRF: repeating_hindrances_-KzIcZW1a8qKlEmw8h8S_hindrancedescription VM23:695 ### value to be set (repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription: undefined (unknown) ******************** (unknown) 1-1) Current value of getMRF: repeating_mhindrances_-kyw394gx2vxyfm1tvb1_mhindrancedescription (unknown) ***** New Row ID: -KzIcZW2jP0LCFEew7-4 ***** VM23:694 ### Loop Number: 3 VM23:695 ### value to be set (repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription: undefined (unknown) ******************** (unknown) ** mookRF: repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrance (unknown) ** wcRF: repeating_hindrances_-KzIcZW2jP0LCFEew7-4_hindrance (unknown) ******************** (unknown) 2-0) Current value of getMRF: repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrance (unknown) ******************** VM23:694 ### Loop Number: 3 (unknown) ** mookRF: repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription VM23:695 ### value to be set (repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription: undefined (unknown) ** wcRF: repeating_hindrances_-KzIcZW2jP0LCFEew7-4_hindrancedescription (unknown) ******************** (unknown) 2-1) Current value of getMRF: repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription VM23:694 ### Loop Number: 3 VM23:695 ### value to be set (repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription: Something positive (unknown) ### Loop Number: 3 (unknown) ### value to be set (repeating_mhindrances_-kyw3bls4suvhagyi113_mhindrancedescription: undefined
1511091527
Jakob
Sheet Author
API Scripter
That's a subtle issue with asynchronous operations and wiuld be solved by the technique I was alluding to. I'll try to explain more when I'm at a proper PC.
1511099467
Jakob
Sheet Author
API Scripter
So the problem is that getAttrs is asynchronous. It runs through the loop indexed by r, and some time later  all your second argument to getAttrs are actually executed. By that time, of course, r is already equal to the last index, which is why it only looks at the last attribute for each row. You could kind of hack that together by baking the index r into the function, but let me tell you how to do it better instead. First you construct an array containing all attributes you would ever get in that inner loop. So that array would contain  repeating_" + mookSection + "_" + idArray[i] + "_m" + fieldArray[r] for all applicable indices i and r. Then you getAttrs() all those attributes at once, and in the argument to that getAttrs() you define a new object sattrs = {}; and   then you can loop over all the i's and r's to set new properties of sattrs. And at the end, after the loops, you setAttrs(sattrs) to finally set everything. This way, you can avoid the weirdness that comes with looping over asynchronous functions. Schematically (and I tried to stay as close as I could to your code): getSectionIDs(mookRS, function (idArray) { const oldAttrs = /* construct an array containing all the attribute names you want here */ getAttrs(oldAttrs, function (v) { const sattrs = {}; for(var i=0; i < idArray.length; i++) { // ... for(var r=0; r < fieldArray.length; r++) { // ... sattrs[putWCRF]=v[getMRF]; } } setAttrs(sattrs); }); });
1511188693

Edited 1511189501
chris b.
Pro
Sheet Author
API Scripter
yes either the above, or I have also made the getattrs line into its own function. That way you are passing variables into a separate function, and they won't change on you as the outer loop changes since they are in their own space in memory. but doing as Jakob says is a LOT faster esp for something like where you are setting tons of attributes. I have a little utility function to build the array of attribute names for a repeating section. It appends every string in every array to each other in every combination, based on the order passed in: /** Append values of multiple arrays of strings together to return one NEW array of strings that is the cartesian product.  * @example cartesianAppend(["a","b"],["c","d"], ["e","f"]); returns ["ace","acf","ade","adf","bce","bcf","bde","bdf"]  * @example cartesianAppend(["pre_"] , ["a","b","c"], ["_post"] ); returns ["pre_a_post","pre_b_post","pre_c_post"]  * @param {Array} [...] Arrays of strings  * @returns {Array} of all values in other arrays  */ export function cartesianAppend () { return _.reduce(arguments, function (a, b) { return _.flatten(_.map(a, function (x) { return _.map(b, function (y) { return String(x) + String(y); }); }), true); }, [[]]); } so in Jakob's example you'd use: //where mookSection="repeating_mooks" or something: oldAttrs=cartesianAppend([mookSection],["_"],idArray,["_"],fieldArray)
Is there anyway yawl could switch to English?  Google translate can't explain to me what yawl are talking about.
1511189323

Edited 1511191449
Finderski
Pro
Sheet Author
Compendium Curator
Jakob and chris: Thanks for your help...I hope to get some time today to give these suggestions a try...you can be sure I'll post here if (when?) I run into trouble... Coal Powered Puppet said: Is there anyway yawl could switch to English?  Google translate can't explain to me what yawl are talking about. LOL—I'll feel you, CPP...I'm barely scraping by and wondering, "Why oh why didn't I take the blue pill?"
1511190846
vÍnce
Pro
Sheet Author
Coal Powered Puppet said: Is there anyway yawl could switch to English?  Google translate can't explain to me what yawl are talking about. You read my mind. ;-P
1511191076
Jakob
Sheet Author
API Scripter
Now I'm sad, I tried to be as explicit as possible :(.
1511191360
chris b.
Pro
Sheet Author
API Scripter
does not compute
1511214724
Finderski
Pro
Sheet Author
Compendium Curator
I gotta thank Jakob and chris b.! You guys rock...I got it working.  And I've tested it with several different repeating fields and it's working for all of them. Thanks, again!