# Difference between revisions of "RepeatingSum"

### From Roll20 Wiki

(Created page with "One request that crops up on the roll20 forums over and over again, is how can you add up all the items in a repeating section? Say you have an inventory section, listing the...") |
m (→repeatingSum Function) |
||

(16 intermediate revisions by 2 users not shown) | |||

Line 6: | Line 6: | ||

== repeatingSum Function == | == repeatingSum Function == | ||

− | Include the following function in the sheet worker script section of your character sheet | + | Include the following function in the sheet worker script section of your character sheet. ) |

<pre> | <pre> | ||

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

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

section = name of repeating fieldset, without the repeating_ | 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 = (destination, section, fields, multiplier = 1) => { | |

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

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

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

− | getSectionIDs(`repeating_${section}`, | + | getAttrs(attrArray, v => { |

− | const | + | |

− | + | ||

− | getAttrs( | + | |

console.log("===== values of v: "+ JSON.stringify(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 | + | 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}); | |

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | setAttrs({[destination]: sumTotal * | + | |

}); | }); | ||

}); | }); | ||

− | } | + | }; |

</pre> | </pre> | ||

+ | |||

== Using The Function == | == Using The Function == | ||

+ | === Simple Example === | ||

Let's say you have an fieldset called '''repeating_inventory''', and in that set you have fields '''item_name''' and '''item_weight'''. You want to sum all the weights, and show that in an attribute outside the fieldset named '''encumbrance_total'''. | Let's say you have an fieldset called '''repeating_inventory''', and in that set you have fields '''item_name''' and '''item_weight'''. You want to sum all the weights, and show that in an attribute outside the fieldset named '''encumbrance_total'''. | ||

Line 47: | Line 41: | ||

}); | }); | ||

</pre> | </pre> | ||

− | + | === Weight * Number === | |

Most inventory lists are a little more complicated. You might have an extra field named '''item_number'''. For instance, your equipment list might include: | Most inventory lists are a little more complicated. You might have an extra field named '''item_number'''. For instance, your equipment list might include: | ||

<pre> | <pre> | ||

Line 56: | Line 50: | ||

<pre> | <pre> | ||

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

− | repeatingSum("encumbrance_total","inventory","item_weight","item_number"); | + | repeatingSum("encumbrance_total","inventory",["item_weight","item_number"]); |

}); | }); | ||

</pre> | </pre> | ||

+ | When using multiple inputs multiplied together, set them up as an array of attribute names, like: ['weight','number'], instead of 'weight'. | ||

− | You could use it for conditional items. Let's say you have a '''repeating_armour''' fieldset, with field names, '''armour_piece''' and '''armour_worn'''. Armour_worn is a checkbox | + | === Conditional Sums (e.g. using a Checkbox) === |

+ | You could use it for conditional items. Let's say you have a '''repeating_armour''' fieldset, with field names, '''armour_piece''' and '''armour_worn'''. Armour_worn is a checkbox. So, you can list a variety of armours, and decide which ones you are wearing by ticking the checkbox. The following function would total the worn armour pieces and add it to an '''armour_weight''' attribute, and ignore the armour not being worn. | ||

<pre> | <pre> | ||

on('change:repeating_armour remove:repeating_armour', function() { | on('change:repeating_armour remove:repeating_armour', function() { | ||

− | repeatingSum("armour_weight", "armour","armour_piece","armour_worn"); | + | repeatingSum("armour_weight", "armour",["armour_piece","armour_worn"]); |

}); | }); | ||

</pre> | </pre> | ||

+ | Note: this works because the a checked Checkbox has a default value of 'on' when checked, and '0' when unchecked. This script treats any text value as a number value of 1, so even if you don't set a value for the checkbox in the html, this will work. | ||

+ | === Multiplying the Total === | ||

For a final example, lets say you have a '''repeating_coinage''' fieldset, with fields '''coin_name''', '''coin_value''', and '''coin_number'''. In this set, names and values are fixed (copper, 1, silver, 10, gold, 100), and players enter the number of each they have. You want to report (a) the total value, and (b) the total weight of the coins. | For a final example, lets say you have a '''repeating_coinage''' fieldset, with fields '''coin_name''', '''coin_value''', and '''coin_number'''. In this set, names and values are fixed (copper, 1, silver, 10, gold, 100), and players enter the number of each they have. You want to report (a) the total value, and (b) the total weight of the coins. | ||

<pre> | <pre> | ||

on('change:repeating_coinage remove:repeating_coinage', function() { | on('change:repeating_coinage remove:repeating_coinage', function() { | ||

− | repeatingSum("total_coin_value", "coinage", "coin_number", "coin_value"); | + | repeatingSum("total_coin_value", "coinage", ["coin_number", "coin_value"]); |

− | repeatingSum("total_coin_weight", "coinage", "coin_number", "coin_weight", '0.02'); | + | repeatingSum("total_coin_weight", "coinage", ["coin_number", "coin_weight"], '0.02'); |

}); | }); | ||

</pre> | </pre> | ||

− | The first repeatingSum above multiples the number gold coins by | + | The first repeatingSum above multiples the number gold coins by gold value, adds that to the number of silver coins multiplied by silver value, and adds to that the number of copper coins multiplied by copper value. |

The second repeatingSum does the same for weights, but then multiples the total weight by 0.02 (so you get 50 coins per pound). This allows you to list coin weights as relative weights - lets say copper and silver coins both weigh then same, so the coin_weight is 1 for those. But gold coins are heavier and have a coin_weight of 2. | The second repeatingSum does the same for weights, but then multiples the total weight by 0.02 (so you get 50 coins per pound). This allows you to list coin weights as relative weights - lets say copper and silver coins both weigh then same, so the coin_weight is 1 for those. But gold coins are heavier and have a coin_weight of 2. | ||

− | + | ||

− | + | '''Author:''' [https://app.roll20.net/users/157788 GiGs](G-G-G on github), with help from [https://app.roll20.net/users/104025 The Aaron], inspired by a [https://app.roll20.net/forum/permalink/6857889/ script created by Finderski]. | |

− | + | ||

− | + | ==See Also== | |

− | + | * [[Sheetworker_examples_for_Non-programmers|Sheetworker Examples for Non-programmers]] | |

− | + | * [[Sheet_Worker_Snippets|Sheet Worker Snippets]] | |

− | + | * [[UniversalSheetWorkers|Universal Sheet Workers]] | |

− | + | * [https://app.roll20.net/forum/post/6963354/build-lookup-table-into-a-character-sheet/?pageforid=6964447#post-6964447 How to integrate table of stats into a sheet] | |

− | + | ||

− | + | <br> | |

− | + | <br> | |

− | + | ||

− | + | __FORCETOC__ | |

− | + | [[Category:Tips]] | |

− | + | [[Category:Guides]] | |

− | + | [[Category:Sheetworker]] | |

− | + | [[Category:Character Sheet Creation]] | |

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + | ||

− | + |

## Revision as of 18:15, 6 July 2019

One request that crops up on the roll20 forums over and over again, is how can you add up all the items in a repeating section?

Say you have an inventory section, listing the items you are carrying, and you need their total weight. Or you have section listing all the coins of different types, and you want their values. Or a skill or power section, and you want the total character points used to buy them.

The sheet worker function below will do that for you. Some examples of how to use it are listed below.

## Contents |

## repeatingSum Function

Include the following function in the sheet worker script section of your character sheet. )

/* ===== 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 = (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}); }); }); };

## Using The Function

### Simple Example

Let's say you have an fieldset called **repeating_inventory**, and in that set you have fields **item_name** and **item_weight**. You want to sum all the weights, and show that in an attribute outside the fieldset named **encumbrance_total**.

You'd add the above function, and the following one:

on('change:repeating_inventory remove:repeating_inventory', function() { repeatingSum("encumbrance_total","inventory","item_weight"); });

### Weight * Number

Most inventory lists are a little more complicated. You might have an extra field named **item_number**. For instance, your equipment list might include:

item_name: bow, item_weight: 3, item_number: 1 item_name: arrows: item_weight: 0.1, item_number: 20

and so on. In this case, you'd use the following function:

on('change:repeating_inventory remove:repeating_inventory', function() { repeatingSum("encumbrance_total","inventory",["item_weight","item_number"]); });

When using multiple inputs multiplied together, set them up as an array of attribute names, like: ['weight','number'], instead of 'weight'.

### Conditional Sums (e.g. using a Checkbox)

You could use it for conditional items. Let's say you have a **repeating_armour** fieldset, with field names, **armour_piece** and **armour_worn**. Armour_worn is a checkbox. So, you can list a variety of armours, and decide which ones you are wearing by ticking the checkbox. The following function would total the worn armour pieces and add it to an **armour_weight** attribute, and ignore the armour not being worn.

on('change:repeating_armour remove:repeating_armour', function() { repeatingSum("armour_weight", "armour",["armour_piece","armour_worn"]); });

Note: this works because the a checked Checkbox has a default value of 'on' when checked, and '0' when unchecked. This script treats any text value as a number value of 1, so even if you don't set a value for the checkbox in the html, this will work.

### Multiplying the Total

For a final example, lets say you have a **repeating_coinage** fieldset, with fields **coin_name**, **coin_value**, and **coin_number**. In this set, names and values are fixed (copper, 1, silver, 10, gold, 100), and players enter the number of each they have. You want to report (a) the total value, and (b) the total weight of the coins.

on('change:repeating_coinage remove:repeating_coinage', function() { repeatingSum("total_coin_value", "coinage", ["coin_number", "coin_value"]); repeatingSum("total_coin_weight", "coinage", ["coin_number", "coin_weight"], '0.02'); });

The first repeatingSum above multiples the number gold coins by gold value, adds that to the number of silver coins multiplied by silver value, and adds to that the number of copper coins multiplied by copper value. The second repeatingSum does the same for weights, but then multiples the total weight by 0.02 (so you get 50 coins per pound). This allows you to list coin weights as relative weights - lets say copper and silver coins both weigh then same, so the coin_weight is 1 for those. But gold coins are heavier and have a coin_weight of 2.

**Author:** GiGs(G-G-G on github), with help from The Aaron, inspired by a script created by Finderski.

## See Also

- Sheetworker Examples for Non-programmers
- Sheet Worker Snippets
- Universal Sheet Workers
- How to integrate table of stats into a sheet