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

Calculation from multiple fields

1563239916

Edited 1563240153
Ray
Pro
Greetings. I have two <Select> fields, attr_birthday and attr_birthmonth. How can I create an attribute based on the selected values of these attributes? Here is my code:         <div>             <div class="field80 right">Birth Day</div>             <select class="input70 center" name="attr_birthday">                 <option>Select</option>                 <option>1st</option><option>2nd</option><option>3rd</option><option>4th</option><option>5th</option>                 <option>6th</option><option>7th</option><option>8th</option><option>9th</option><option>10th</option>                 <option>11th</option><option>12th</option><option>13th</option><option>14th</option><option>15th</option>                 <option>16th</option><option>17th</option><option>18th</option><option>19th</option><option>20th</option>                 <option>21st</option><option>22nd</option><option>23rd</option><option>24th</option><option>25th</option>                 <option>26th</option><option>27th</option><option>28th</option><option>29th</option><option>30th</option>             </select>             <div class="field40 right">Month</div>             <select class="input200" name="attr_birthmonth">                 <option>Select</option>                 <option>Nuzyael (Early Spring)</option><option>Peonu (Mid Spring)</option><option>Kelen (Late Spring)</option>                 <option>Nolus (Early Summer)</option><option>Larane (Mid Summer)</option><option>Agrazhar (Late Summer)</option>                 <option>Azura (Early Autumn)</option><option>Halane (Mid Autumn)</option><option>Savor (Late Autumn)</option>                 <option>Ilvin (Early Winter)</option><option>Navek (Mid Winter)</option><option>Morgat (Late Winter)</option>             </select>         </div>
1563248199

Edited 1563248555
GiGs
Pro
Sheet Author
API Scripter
How do you calculate the value of the desired attribute? What should it look like? You can use a sheet worker or an autocalc field, and if its just a text output, this is one case where an autocalc field might have no drawbacks. But if you want to process each of the two attributes in some way, a sheet worker will be needed. Edit:  I see where you might be having a problem. With a select, you need to set the value on each option.   <option value="1st">1st</option> or    <option value="1">1st</option> The text between the <option> </option> tags is just displayed on the character sheet. It is not stored in the attribute. For that you need the value tag.
1563249333

Edited 1563249375
Ray
Pro
GiGs said: How do you calculate the value of the desired attribute? What should it look like? You can use a sheet worker or an autocalc field, and if its just a text output, this is one case where an autocalc field might have no drawbacks. But if you want to process each of the two attributes in some way, a sheet worker will be needed. Edit:  I see where you might be having a problem. With a select, you need to set the value on each option.   <option value="1st">1st</option> or    <option value="1">1st</option> Hi GiGs...I figured that out a short while ago.  ;) The purpose of this exercise is to determine a characters "sunsign"...just like a zodiac calendar. So, I have set numeric values for each of the selects...a value of 1-30 for the "birthday" attribute, and a value of 1-12 for the "birthmonth" attribute. With some simple maths in the sheetworker I can produce a value from 1-360 as a date of birth within the calendar year. What I want to do now is output some text to a field in the sheet. This text is dependent on the numeric value of the calculation. I also want this output to be readonly. How can I do this?
1563250977
GiGs
Pro
Sheet Author
API Scripter
It would be a lot easier if you told me the rules for the calculation. Also, the attribute name for the output. I've called it resultattribute  below. But the basics is just the standard sheet worker: on ( "change:birthday change:birthmonth" , function () { getAttrs ([ "birthday", "birthmonth" ], function (values) { const month = values.birthmonth; cont day = values.birthday; let resultattribute = 'default text'; // this is what the attribute will show if player hasnt selected a value. if(!isNaN(month) && !isNaN(day)) { // if both day and month are numbers (so the player has selected values)     const dayofyear = +month * +day; // get a numerical value for day of year      // do your calculation here, before the end of the if statement, and store its value in resultattribute } setAttrs({          resultattribute: resultattribute }); }); }); In order for this to work, you need to set your outputs for the select correctly. The values for months should be 0 to 11, and for days, 0 to 29. For example  <select class="input70 center" name="attr_birthday"> <option value='-'>Selected</option>                 <option value='0' selected>1st</option><option value='1'>2nd</option><option value='2'>3rd</option> The above ensures the first value is always selected, so the sheet worker Finally to make sure your output attribute is readonly, just add the readonly tacg: <input name="attr_resultattribute" value="whatever" readonly />
1563255896

Edited 1563255928
Ray
Pro
Ok...here is what I have so far....         <!-- DEFINE BIRTH DAY, BIRTH MONTH, AND BIRTH YEAR -->         <div>             <div class="field80 right">Birth Day</div>             <select class="input70 center" name="attr_birthday">                 <option>Select</option>                 <option value="1">1st</option><option value="2">2nd</option><option value="3">3rd</option>                 <option value="4">4th</option><option value="5">5th</option><option value="6">6th</option>                 <option value="7">7th</option><option value="8">8th</option><option value="9">9th</option>                 <option value="10">10th</option><option value="11">11th</option><option value="12">12th</option>                 <option value="13">13th</option><option value="14">14th</option><option value="15">15th</option>                 <option value="16">16th</option><option value="17">17th</option><option value="18">18th</option>                 <option value="19">19th</option><option value="20">20th</option><option value="21">21st</option>                 <option value="22">22nd</option><option value="23">23rd</option><option value="24">24th</option>                 <option value="25">25th</option><option value="26">26th</option><option value="27">27th</option>                 <option value="28">28th</option><option value="29">29th</option><option value="30">30th</option>             </select>             <div class="field40 right">Month</div>             <select class="input200" name="attr_birthmonth">                 <option>Select</option>                 <option value="1">Nuzyael (Early Spring)</option>                 <option value="2">Peonu (Mid Spring)</option>                 <option value="3">Kelen (Late Spring)</option>                 <option value="4">Nolus (Early Summer)</option>                 <option value="5">Larane (Mid Summer)</option>                 <option value="6">Agrazhar (Late Summer)</option>                 <option value="7">Azura (Early Autumn)</option>                 <option value="8">Halane (Mid Autumn)</option>                 <option value="9">Savor (Late Autumn)</option>                 <option value="10">Ilvin (Early Winter)</option>                 <option value="11">Navek (Mid Winter)</option>                 <option value="12">Morgat (Late Winter)</option>             </select>             <div class="field30 right">Year</div>             <input class="input50 center" type="number" name="attr_birthyear">             <div class="field30 left">TR</div>         </div>         <!-- DEFINE SUNSIGN -->         <div>             <div class="field80 right">Sunsign</div>                 <input class="input300 left" name="attr_sunsign" value="" readonly>         </div> and here is my sheetworker...     on('change:birthday change:birthmonth sheet:opened', function () {         getAttrs(['birthday','birthmonth'], function(v) {             const birthday = v.birthday *1||0;             const birthmonth = v.birthmonth *1||0;             const month = Math.floor(birthmonth*30 - 30);             const sunsign = Math.floor(birthday + month);             setAttrs({                  birthday: birthday,                  birthmonth: birthmonth,                  sunsign: sunsign             });         });     }); So....attr_sunsign can (at this point) have a numeric value from 1 to 360...all good so far... What I want to do is convert each of those 360 numeric values into text...for example 1-20 = Aries, 21-35 = Capricorn...etc
1563262094
GiGs
Pro
Sheet Author
API Scripter
You have two issues with your calculation:  first, you have no value in the Select option. This means it will sometimes have an empty, null, or undefined value (not sure which). Since you convert any of these values to a number, your worker will return a value of 0 for those results. This is still a result! It will return a sunsign, even though there isnt one. The way I handled it was setting a value of "-" and having an if statement that checks for non-numeric values. I also didnt coerce the month and day into integers till after I checked if they were numbers (putting the + before them is a short way to convert them to numbers). With this approach, you can set a default value for the sunsign attribute for when no valid sunsign exists. This isnt essential, but it's neater. You can also make that month calculation a bit smoother. Finally, you do not need brthday and birthmonth in the setttrs section. They already exist, and aren't changing, so you dont need to set them again. These fixes would look like this on ( "change:birthday change:birthmonth" , function () { getAttrs ([ "birthday", "birthmonth" ], function (values) { const month = values.birthmonth; const day = values.birthday; let sunsign = 'Select Day and Month'; if(!isNaN(month) && !isNaN(day)) { // if both day and month are numbers (so the player has selected values)         const dayofyear = (+month -1) * 30 + +day; // get a numerical value for day of year      const sunsigns = {1: "Aries", 21: "Capricorn", }; //etc         sunsign = dayofyear; } setAttrs({          sunsign: sunsign }); }); });
GiGs said: You have two issues with your calculation:  first, you have no value in the Select option. This means it will sometimes have an empty, null, or undefined value (not sure which). Since you convert any of these values to a number, your worker will return a value of 0 for those results. This is still a result! It will return a sunsign, even though there isnt one. The way I handled it was setting a value of "-" and having an if statement that checks for non-numeric values. I also didnt coerce the month and day into integers till after I checked if they were numbers (putting the + before them is a short way to convert them to numbers). With this approach, you can set a default value for the sunsign attribute for when no valid sunsign exists. This isnt essential, but it's neater. You can also make that month calculation a bit smoother. Finally, you do not need brthday and birthmonth in the setttrs section. They already exist, and aren't changing, so you dont need to set them again. These fixes would look like this on ( "change:birthday change:birthmonth" , function () { getAttrs ([ "birthday", "birthmonth" ], function (values) { const month = values.birthmonth; const day = values.birthday; let sunsign = 'Select Day and Month'; if(!isNaN(month) && !isNaN(day)) { // if both day and month are numbers (so the player has selected values)         const dayofyear = (+month -1) * 30 + +day; // get a numerical value for day of year      const sunsigns = {1: "Aries", 21: "Capricorn", }; //etc         sunsign = dayofyear; } setAttrs({          sunsign: sunsign }); }); }); GiGs...you totally rock!  :D I will try it out...
1563262749

Edited 1563264948
GiGs
Pro
Sheet Author
API Scripter
I hit send a bit too quick - still thinking about the best way to do the sunsigns. The easiest but least elegant way is to use if/else, as follows: replace this line sunsign = dayofyear; with if(dayofyear < 21) sunsign = 'Aries'; else if (dayofyear < 36) sunsign = 'Capricorn'; else if /// and so on for each sign till we are back to aries again: else sunsign = 'Aries'; I also realised after the fact, it's a good idea to put selected in the month and day select html like so  <option value='-' selected>Select</option> and add sheet:opened  to the sheet worker on ( "change:birthday change:birthmonth sheet:opened", function () { This is to make sure sunsign gets set properly to its default value when you first open the sheet, and any existing characters get it set properly.
1563264465
GiGs
Pro
Sheet Author
API Scripter
Okay, here's a more elegant version, using a technique I learned from Aaron. on("change:birthday change:birthmonth sheet:opened", function () { getAttrs(["birthday", "birthmonth"], function (values) { // an array of sunsigns. Add a new row for each sign in the format: {day: x, sign: 'name'}, and x is the first day of the year for that sign. const sunsignByDay = [ {day: 1, sign: 'Aries'}, {day: 21, sign: 'Capricorn'}, {day: 36, sign: 'Aquarius' }, ].reverse(); // a function to get the sign, given the day of year. const getSign = (d) => { const entry = sunsignByDay.find((o) => o.day <= d); return (entry && entry.sign) || sunsign; }; const month = values.birthmonth; const day = values.birthday; // default value of sunsign, for when no valid entry is found: let sunsign = 'Select Day and Month'; // check if month and day are numbers (they can be '-' or null if dont set a selected tag on the Selects) if (!isNaN(month) && !isNaN(day)) { const dayofyear = (+month - 1) * 30 + +day; // get a numerical value for day of year sunsign = getSign(dayofyear); } setAttrs({ sunsign: sunsign }); }); }); The bit you need to edit is this     const sunsignByDay = [ {day: 1, sign: 'Aries'}, {day: 21, sign: 'Capricorn'}, {day: 36, sign: 'Aquarius' }, ].reverse(); You need to add a row for each sunsign, in the same format. The day is the 1st day of the year for that sunsign. Make sure you add them in the right order. If you you have 12 sunsigns like earth, you'll get Aries a second time during the last month - that's okay, you add it again at the bottom of the list.
GiGs...you are a legend mate. I have added the code and tweaked it slightly for my game, and it's working perfectly. Thanks so much...really appreciated  :D
1563299368
GiGs
Pro
Sheet Author
API Scripter
Yay :) You're welcome.