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 Streamline/Optimize Sheetworker Script

In my D&D 3.5 custom sheet I track up to four classes and 52 skills. I am tracking skill points spent by class (for class/cross-class purposes). To display unspent skill points by class (skillpoints01_unspent, skillpoints02_unspent, etc.), I have the following "brute force" sheetworker in my sheet four times (once for each class: class01, class02, etc.). This code works, but it is ugly and I am sure it could be more economical and efficient and have it check each class and skill all in one go, but Javascripting is cross-class for me. :-) I am sure I need to use let and make arrays of the skillnames and an array of class01-class04, and use map and loop through. I also have The Aaron Sheet included and that can probably help make a running total through the loops. For the sample code below I have eliminated most of the skills and listed just for class01 to keep the code brief. Any advice/assistance/suggestions/scriptomancy appreciated! on("sheet:opened change:character_level change:acrobatics_class01_points \ change:appraise_class01_points change:bluff_class01_points change:climb_class01_points \ change:craft1_class01_points change:craft2_class01_points change:craft3_class01_points", function() {   getAttrs(["class01_skillpoints", "acrobatics_class01_points", "appraise_class01_points",   "bluff_class01_points", "climb_class01_points", "craft1_class01_points",   "craft2_class01_points", "craft3_class01_points"], function(values) {     setAttrs({         "skillpoints01_unspent": (parseInt(values["class01_skillpoints"],10) || 0) - (             (parseInt(values["acrobatics_class01_points"],10) || 0) +         (parseInt(values["appraise_class01_points"],10) || 0) +         (parseInt(values["bluff_class01_points"],10) || 0) +         (parseInt(values["climb_class01_points"],10) || 0) +         (parseInt(values["craft1_class01_points"],10) || 0) +         (parseInt(values["craft2_class01_points"],10) || 0) +         (parseInt(values["craft3_class01_points"],10) || 0)             )         });     }); });
1512745804
The Aaron
Pro
API Scripter
The Aaron Sheet only helps with Repeating Sections right now.  Something like this might help: const classes = [ '01', '02', '03', '04' ]; const skills = [ 'acrobatics', 'appraise', 'bluff', 'climb', 'craft1', 'craft2', 'craft3' ]; const skillAttrs = _.map(classes,(c)=>_.map(skills, (s)=>`${s}_class${c}_points`)); const skillEvents = _.map(skillAttrs,(a)=>`change:${a}`); const pointsAttrs = _.map(classes,(c)=>`class${c}_skillpoints`); on(`sheet:opened ${skillEvents.join(' ')}`, function() {   getAttrs(Array.concat(skillAttrs,pointsAttrs), (values) =>{     let update = {};         _.each(classes, (c)=>{             update[`skillpoints${c}_unspent`]=(parseInt(values[`class${c}_skillpoints`],10)||0) - _.reduce(                 _.map(skills, (s) => parseInt(values[`${s}_class${c}_points`],10)||0 ),                 (m,p) => m+p,                 0);         });     setAttrs(update);   }); }); Note that you might need to replace all the `${stuff}_${other}` things with traditional stuff+"_"+other type things. 
That's what I am talking about. That code is about 10% the length of what I have now. Many, many thanks, TheAaron! I will test this out later today! :-)
1512842636
The Aaron
Pro
API Scripter
Cheers. =D
1512844262
Jakob
Sheet Author
API Scripter
The only issue I have with this is that it's using Underscore, not native map() and forEach() and reduce() - but that's a matter of opinion :).
Hmmm... not working. When you say The Aaron said: Note that you might need to replace all the `${stuff}_${other}` things with traditional stuff+"_"+other type things. Do you mean I should do this? const skillAttrs = _.map(classes,(c)=>_.map(skills, (s)=>`${s} + '_class' + ${c} + '_points'`));
1512846760
Jakob
Sheet Author
API Scripter
Rabulias said: Hmmm... not working. When you say The Aaron said: Note that you might need to replace all the `${stuff}_${other}` things with traditional stuff+"_"+other type things. Do you mean I should do this? const skillAttrs = _.map(classes,(c)=>_.map(skills, (s)=>`${s} + '_class' + ${c} + '_points'`)); I wouldn't replace anything like that at all - but when you do it like this, you'd use const skillAttrs = _.map(classes,(c)=>_.map(skills, (s)=> s + '_class' + c + '_points')); The following expressions are equivalent: s + '_class' + c + '_points' `${s}_class${c}_points`
1512851850
The Aaron
Pro
API Scripter
The back ticket ` strings are called Template Literals:&nbsp; <a href="https://developer.mozilla.org/en-US/docs/Web/JavaS" rel="nofollow">https://developer.mozilla.org/en-US/docs/Web/JavaS</a>... They're really great, the only reason I mentioned the possibility of replacing them is because they might not be supported on older browsers (Any of the ones Roll20 supports should be fine, but some people use other browsers anyway.&nbsp;&nbsp; CanIUse.com shows IE11 and some mobile browsers not supporting them.
1512851940
The Aaron
Pro
API Scripter
Jakob said: The only issue I have with this is that it's using Underscore, not native map() and forEach() and reduce() - but that's a matter of opinion :). Yeah, I almost removed those, but they're really handy, known to be included, and I don't have to look up the syntax. =D
1512852002
The Aaron
Pro
API Scripter
Rabulias said: Hmmm... not working. When you say So, are you getting an error?
1512857419

Edited 1512859198
No error message that I can see in the console. I console.log()'d some things and I can see that skillEvents is not getting created properly, generating: change: acrobatics_class01_points,appraise_class01_points,bluff_class01_points,climb_class01_points, craft1_class01_points,craft2_class01_points,craft3_class01_points, change: acrobatics_class02_points, appraise_class02_points,bluff_class02_points,climb_class02_points,craft1_class02_points, craft2_class02_points,craft3_class02_points, change: acrobatics_class03_points,appraise_class03_points, bluff_class03_points,climb_class03_points,craft1_class03_points,craft2_class03_points,craft3_class03_points, change: acrobatics_class04_points,appraise_class04_points,bluff_class04_points,climb_class04_points, craft1_class04_points,craft2_class04_points,craft3_class04_points The change: directive is just at the beginning of each set per class, not on each skill.
Also, general sheetworker question: I assume I can't use the same variable names elsewhere in sheetworkers, right? If I use let skills = or const skills = here, another block of code with let skills = will cause problems?
1512860710
The Aaron
Pro
API Scripter
Ah!&nbsp; Replace with this line: const skillAttrs = _.flatten(_.map(classes,(c)=&gt;_.map(skills, (s)=&gt;`${s}_class${c}_points`)));
1512927964

Edited 1512929081
Jakob
Sheet Author
API Scripter
Rabulias said: Also, general sheetworker question: I assume I can't use the same variable names elsewhere in sheetworkers, right? If I use let skills = or const skills = here, another block of code with let skills = will cause problems? Yes, if you also use declare them globally (not within a function). Declaring them again within another function is fine. There are ways to encapsulate this definition to not expose the variables to the global scope, if you need to use the same variable names in another context. On the plus side, it will give a Syntax Error rather than fail silently or just use one value over the other (as it would when using var ). So it's actually quite easy to detect if you check your code for syntax errors using some kind of linter.
Wahoo! It's working great! Many thanks again, TheAaron! I did need to rename the consts; thanks for the word on declaration, Jakob. Any easy summary/reference on declaring them globally vs encapsulating them? I can see some of these&nbsp;being available globally in multiple sheetworker functions (like the array named "skills" that lists all 52 skills so I don't have to copy it over and over again). Others I would want to use solely in one function without worrying about using the same array name elsewhere.
1513083440
The Aaron
Pro
API Scripter
const and let are block scoped, so you could just put a block around the ones you want to share the definition: const skills=... // everyone { const classes=... // this block on(‘change:thing1... on(‘change:thing2... } { const classes=... // this block on(‘change:thing3... }