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 Explain This [Working] Sheet Worker To Me

To be clear, this sheet worker actually works, for once. :) I haven't tested it extensively yet, but early tests are positive. Its a stripped out version of the sheetworker from the old L5R sheet. That's why all the structure is there for converting data from repeating sections, even though there's no repeating data to convert this time. Basically, I've got this as a structure going forward. (I'll clean up before I publish). My intention is to copy and paste it every time Fantasy Flight changes a major element of the game in beta and I need to rename a non-derived variable because of it. So this is the first one, and they renamed "Resilience" to "Endurance." That stat is derived for PCs, so no worries there, just an orphaned variable on the sheet, but for NPCs, that stat is hand-picked and not derived from stats, so it needs to be converted by the sheetworker, which this seems to do without issue. Actually, a lot of this is a bit beyond me in syntax, I believe Brian and Jakob did most of the work, but I think Jakob the part I'm most curious about, and that's the section that checks, sees that there's no version number variable, and runs the sheetworker function. I need to understand how that works. Can you explain that well enough (or how to change it) so that when I have to write the next one, to check for version 0.8.1 and change it version X, I know how that bit of code changes? This I think checks to see if the variable is missing and runs the code. If I'm just moving variables around, I can probably do the rest, but I'm not sure how that If statement works well enough to alter it, because I don't understand the syntax well enough to know what parts to change.  var convertFromOldSheet = function () { // Non-repeating attributes to rename let conversionData = { 'npc_resilience': 'npc_endurance' }, // Repeating attributes to rename; this assumes that the section name, e.g. // repeating_spell, does NOT change, so make sure that that is the case or // it will need quite a bit mor work conversionDataRepeating = { }; // Non-repeating attribute renaming getAttrs(Object.keys(conversionData), function (values) { let setting = {}; Object.keys(conversionData).forEach(function (oldAttr) { if (values[oldAttr] != null) { // set value of new attribute to the old one setting[conversionData[oldAttr]] = values[oldAttr]; // blank old attribute setting[oldAttr] = ''; } }); setAttrs(setting, {silent: true}); // set things silently to make sure we do not trigger unwanted changes }); // Repeating attribute renaming - loop through all sections, and loop through all ids // and all attributes for every section Object.keys(conversionDataRepeating).forEach(function (sectionName) { let data = conversionDataRepeating[sectionName]; getSectionIDs(sectionName, function (idArray) { let oldAttrs = idArray.reduce(function (m, id) { return m.concat(Object.keys(data).map(name => `${sectionName}_${id}_${name}`)); }, []); getAttrs(oldAttrs, function (values) { let setting = {}; idArray.forEach(function (id) { Object.keys(data).forEach(function (oldAttr) { if (values[`${sectionName}_${id}_${oldAttr}`] != null) { // set value of new attribute to the old one setting[`${sectionName}_${id}_${data[oldAttr]}`] = values[`${sectionName}_${id}_${oldAttr}`]; // blank old attribute setting[`${sectionName}_${id}_${oldAttr}`] = ''; } }); }); setAttrs(setting, {silent: true}); // set things silently to make sure we do not trigger unwanted changes }); }); }); }; on('sheet:opened', function () { let currentVersion = '0.8.1'; getAttrs(['version'], function (v) { if (!v.version) { convertFromOldSheet(); }; setAttrs({ version: currentVersion }); }); });
1511709105
Jakob
Sheet Author
API Scripter
Yes. The if (!v.version) { convertFromOldSheet(); }; bit just checks if v.version is falsy, which will happen if it is one of empty string, undefined, NaN, 0, null, or false. In our case, after version has been set once, it's some non-empty string, so v.version === '0.8.1', in particular it's not falsy and so that if clause never runs. Initially, v.version is undefined as there's no version attribute on the sheet. What you want to add is some kind of upgrade immediately after that else { upgradeSheet(v.version); } Then you need to write the upgradeSheet function. I imagine that at the start you should find out all the parts of your version number, something like this: const upgradeSheet = function (version) { const versionSplit = version.split('.'), majorVersion = parseInt(versionSplit[0]), minorVersion = parseInt(versionSplit[1]), patchVersion = parseInt(versionSplit[2]); // .. } After that, you can do some conditional statements to check the sheet's version and upgrade from that if it's lower than the current one.
What if I just wanted to add a second one that checked if version equals 0.8.1? I don't know if this will happen often enough to warrent all the parsing.
1511982940
Lithl
Pro
Sheet Author
API Scripter
The Exalted 3rd edition sheet has a pretty good example, IMO: var version = 2.3; // ... other stuff ... on('sheet:opened', TAS._fn(function upgradeVersion(e) {     TAS.debug('Checking version', e);     getAttrs(['version', 'exalt-type'], TAS._fn(function versionCheck(values) {         var v = parseFloat(values.version);         if (v !== version) {             switch (v) {                 default:                     if (values['exalt-type'] && values['exalt-type'].length > 0) {                         // version 1                         upgradeV1toV2();                     } else {                         // new character break;                     }                     // fallthrough                 case 2:                     // upgrade v2 to v2.1                     // fallthrough                 case 2.1:                     // upgrade v2.1 to v2.2                     // fallthrough case 2.2: // upgrade v2.2 to v2.3 // fallthrough             } setAttrs({version: version});         }     })); })); This switch with fallthrough cases allows for incremental version upgrades. This means the author only has to know the logic for upgrading between two versions, instead of each pair of versions. There's no need to write the logic for upgrading from v1 -> v2, v1 -> v2.1, v1 -> v2.2, v1 -> v2.3, v2 -> v2.1, v2 -> v2.2, v2 -> v2.3, v2.1 -> v2.2, v2.1 -> v2.3, and v2.2 -> v2.3. Instead, you only need logic for v1 -> v2, v2 -> v2.1, v2.1 -> v2.2, and v2.2 -> v2.3. (In the case of this particular sheet, no actual logic is needed except v1 -> v2, of course.) If a user created a character with the version 1 sheet, left for a while, and then came back to the v2.3 sheet, this would perform each version upgrade all at once, in order. The default case is special, because v1 of the sheet had no version attribute, so it needs some way to distinguish between a sheet created under v1 and a new sheet created under the current version. Version is only set by the sheet worker, because if it were set in the HTML, a v1 sheet would immediately have the current version's value upon opening after the version change, which makes the version kinda useless. In the default case, I check for an attribute that only existed in the v1 sheet and was removed in v2. String versions would work just as well in this scheme, simply change var version = ...  to a string value, and remove the parseFloat .
1511987493
Jakob
Sheet Author
API Scripter
Robert D. said: What if I just wanted to add a second one that checked if version equals 0.8.1? I don't know if this will happen often enough to warrent all the parsing. You can just do that, if you don't want to set up the whole infrastructure.