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

RepeatingSum...Help?

July 25 (5 years ago)

Edited July 25 (5 years ago)
Ray
Pro

I have the following which I am trying to adapt for my custom sheet....copied from the Wiki and partially modified.

To be honest, the syntax is beyond me, and I am unsure exactly where to substitute my attribute names.

My attributes are:

destination = "total_wgt"

section = "inventory"

fields = "inv_wgt"

multiplier = "1" (default setting)

I also have a quantity attribute called "inv_qty" which is a modifier for the individual items...

Could someone help me fill in the blanks please?

Here is my HTML

<div class="row">

    <div class="field50 bold">Qty</div>

    <div class="field400 bold">Item</div>

    <div class="field180 center bold">Location</div>

    <div class="field40 center bold">WGT</div>

    <fieldset class="repeating_inventory">

        <input class="field50 left" type="text" name="attr_inv_qty">

        <input class="field400 left" type="text" name="attr_inv_name">

        <input class="field180 left" type="text" name="attr_inv_loc">

        <input class="field40 center" type="number" name="attr_inv_wgt" value="0" step="0.01">

    </fieldset>

</div>

/* ===== PARAMETERS ==========

destination = the name of the attribute that stores the total quantity

section = name of repeating fieldset, without the repeating_

fields = the name of the attribute field to be summed can be a single attribute: 'weight' 

    or an array of attributes: ['weight','number','equipped']

multiplier (optional) = a multiplier to to entire fieldset total. For instance, if summing coins of

weight 0.02, might want to multiply the final total by 0.02. */


const repeatingSum = (total_wgt, inventory, fields, multiplier = 1) => {

    if (!Array.isArray(fields)) fields = [inv_wgt];

    getSectionIDs(`repeating_${inventory}`, idArray => {

        const attrArray = idArray.reduce( (m,id) => [...m, ...(fields.map(field => `repeating_${inventory}_${id}_${inv_wgt}`))],[]);

        getAttrs(attrArray, v => {

            console.log("===== values of v: "+ JSON.stringify(v) +" =====");

                 // getValue: if not a number, returns 1 if it is 'on' (checkbox), otherwise returns 0..

            const getValue = (section, id,field) => parseFloat(v[`repeating_${inventory}_${id}_${field}`], 10) || (v[`repeating_${inventory}_${id}_${field}`] === 'on' ? 1 : 0); 

            const sumTotal = idArray.reduce((total, id) => total + fields.reduce((subtotal,field) => subtotal * getValue(section, id,field),1),0);

            setAttrs({[total_wgt]: sumTotal * multiplier})

        });

    });

};

July 25 (5 years ago)

Edited July 25 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

repeatingSum is meant to be dropped in to your script section without changes. Then you use another sheet worker to activate it. This lets you have just one copy of repeatingSum, and call it multiple times for different totals.

So assuming you copy it exactly from the wiki and put in your script block with no changes, you'd call it with a sheet worker like this:

on('change:inventory_inv_wgt change:inventory_inv_qty remove:repeating_inventory', function() {
	repeatingSum("total_wgt","inventory",["inv_qty","inv_wgt"]);
});

You dont need to include the multiplier of it's the default value.

edit: updated to include the full attributes, after you edited your post.

July 25 (5 years ago)
Ray
Pro


GiGs said:

repeatingSum is meant to be dropped in to your script section without changes. Then you use another sheet worker to activate it. This lets you have just one copy of repeatingSum, and call it multiple times for different totals.

So assuming you copy it exactly from the wiki and put in your script block with no changes, you'd call it with a sheet worker like this:

on('change:inventory_inv_wgt remove:repeating_inventory', function() {
repeatingSum("total_wgt","inventory",["inv_qty","inv_wgt"]); });

You dont need to include the multiplier of it's the default value.

LOL....oh for gods sake....sometimes I am so incredibly stupid, I even surprise myself....  :O

You know GiGs...I looked at that, and I read it, but do you think I actually comprehended it.....NO!  hahaha  *blush*

July 25 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter


Ray said:

LOL....oh for gods sake....sometimes I am so incredibly stupid, I even surprise myself....  :O

You know GiGs...I looked at that, and I read it, but do you think I actually comprehended it.....NO!  hahaha  *blush*

hehe, i often feel that way reading my own code after a few months. 




July 25 (5 years ago)

Edited July 25 (5 years ago)
Ray
Pro

Ok...so I've been playing around with the code...

Here is my HTML...

<div class="row">

    <div class="field50 bold">Qty</div>

    <div class="field500 bold">Item</div>

    <div class="field180 center bold">Location</div>

    <div class="field40 center bold">WGT</div>

    <fieldset class="repeating_inventory">

        <input class="field50 center" type="text" name="attr_inv_qty">

        <input class="field500 left" type="text" name="attr_inv_name">

        <input class="field180 left" type="text" name="attr_inv_loc">

        <input class="field40 center" type="number" name="attr_inv_wgt" value="0" step="0.01">

    </fieldset>

    <div class="field737 right bold">Total Carried Weight</div>

        <input class="input30 center" type="number" name="attr_total_wgt" disabled="true" value="@{total_wgt}" step="0.01">

</div>

And here is my sheetworker...

    const repeatingSum = (destination, section, fields, multiplier = 1) => {

        if (!Array.isArray(fields)) fields = [fields];

        getSectionIDs(`repeating_${section}`, idArray => {

            const attrArray = idArray.reduce( (m,id) => [...m, ...(fields.map(field => `repeating_${section}_${id}_${field}`))],[]);

            getAttrs(attrArray, v => {

                console.log("===== values of v: "+ JSON.stringify(v) +" =====");

                // getValue: if not a number, returns 1 if it is 'on' (checkbox), otherwise returns 0..

                const getValue = (section, id,field) => parseFloat(v[`repeating_${section}_${id}_${field}`], 10) || (v[`repeating_${section}_${id}_${field}`] === 'on' ? 1 : 0); 

                const sumTotal = idArray.reduce((total, id) => total + fields.reduce((subtotal,field) => subtotal * getValue(section, id,field),1),0);

                setAttrs({[destination]: sumTotal * multiplier});    

            });

        });

    };

    on('change:repeating_inventory remove:repeating_inventory', function() {

    repeatingSum("total_wgt","inventory",["inv_wgt","inv_qty"]);

    });

and the result I am getting looks like this....

For some reason that I am failing to see, the attribute "total_wgt" is not going into the appropriate field??


July 25 (5 years ago)

Edited July 25 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

You have total_wgt as an autocalc field. scripts cant change autocalc fields. Also its value is referencing itself, which will never work. Change

<input class="input30 center" type="number" name="attr_total_wgt" disabled="true" value="@{total_wgt}" step="0.01">

to

<input class="input30 center" type="number" name="attr_total_wgt" value="0" step="0.01" readonly>




July 25 (5 years ago)

Edited July 25 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

I'd also recommend tweaking the change line to only trigger when qty and wgt change:

on('change:inventory:inv_wgt change:inventory:inv_qty remove:repeating_inventory', function() {
	repeatingSum("total_wgt","inventory",["inv_qty","inv_wgt"]);
});

This means the sheet worker wont trigger when you change name or location, for instance. That just wastes processor cycles for no effect. This is a bit more efficient.

July 25 (5 years ago)
Ray
Pro


GiGs said:

I'd also recommend tweaking the change line to only trigger when qty and wgt change:

on('change:inventory_inv_wgt change:inventory_inv_qty remove:repeating_inventory', function() {
	repeatingSum("total_wgt","inventory",["inv_qty","inv_wgt"]);
});

This means the sheet worker wont trigger when you change name or location, for instance. That just wastes processor cycles for no effect. This is a bit more efficient.

Excellent improvement....and despite my raging head-cold I had already spotted that one (yay me)  :)

Sadly, I'm still not getting a "total_wgt" though, and I can't see why  :'(


July 25 (5 years ago)
GiGs
Pro
Sheet Author
API Scripter

That's my fault, I used the wrong syntax for the change line. It should be

on('change:inventory:inv_wgt change:inventory:inv_qty remove:repeating_inventory', function() {

I've corrected it above.

July 25 (5 years ago)
Ray
Pro


GiGs said:

That's my fault, I used the wrong syntax for the change line. It should be

on('change:inventory:inv_wgt change:inventory:inv_qty remove:repeating_inventory', function() {

I've corrected it above.

EUREKA!!!  :D  :D  :D

on('change:repeating_inventory:inv_wgt change:repeating_inventory:inv_qty remove:repeating_inventory', function() {

        repeatingSum("total_wgt","inventory",["inv_qty","inv_wgt"]);

});