Calculate value

Value resolver – Abstract

Purpose: Performs mathematical operations with numeric values (with and without unit), and usually returns the calculation result as a 'Unit number' as the return value.

images/download/attachments/201666907/image-2025-3-5_16-14-31-version-1-modificationdate-1743580304025-api-v2.png

The Calculate value value resolver allows mathematical operations with numeric values (with and without unit), and usually returns the calculation result as a 'Unit Number' as the return value.

Exceptions:

  • The calculation expression is empty or contains syntax errors (e.g. regarding bracket replacement). Then the return value is 'No value' ($null), but no error occurs.

  • The calculation expression's syntax is correct, but it is not possible to calculate. Then an error occurs at runtime (e.g. ArithmeticException: Division by zero).

In principle, a calculation expression can serve the sole purpose of defining a 'Unit Number' statically (via text entry in the configuration), for example: 7.5t for the definition of a maximum weight of '7.5 tonnes'.

In most cases, however, the calculation links variable input variables that are at least partially provided via variables.

The calculation expression can be constructed from different components:

Type of component

Syntax/Example

Description

Example of expressions

Result (example)

Constant numerical values
(with and without Units).

<Value>[<Alias of the unit>]

or

<Alias of the unit>(then 1 is assumed as the value)

IMPORTANT◄ Regardless of the settings for the Current locale, the entry of the point as a decimal separator is required.

The unit of a constant must appear after it and be identified via the alias from the relevant dynamic enumeration. Spaces between value and unit are optional.

-1.024
1250kg
123456 USD


USD (= 1 USD)ft (= 1 ft)m3 (= 1 m3)

Constant 'Unit number' (UnitNumber), whose 'value' (value) field specifies a signed decimal number and in the optional 'unit' (unit) field refers to one of the configured Units.

Preset constants
(Override assignments to variables with the same name).

pi

Pi π (3.1415926535897932384...)

radius^2*pi

Circular area for a circle with the radius defined by the radius variable.

e

Euler's number e (2.7182818284590452353...)

ln(e)

1

Automatically preset variables
(Can be overridden by explicit assignments for the same variable name in the inner context (see below) of the Calculate value value resolver).

input

Input value

By default, the input variable is preassigned with the input value, provided this can be converted into a numerical value.

input*1.19

Calculates a gross amount (with a tax rate of 19%) if the input value (input) is a net amount.

NOTE Data field paths for accessing numerically interpretable field values (e.g. input.numericProperty) are resolved exclusively for the input value (input) so that, for example, several input value fields can be calculated without having to be mapped to individual variables.

input.end-input.start


(input.end-input.start)ms


convert((input.end-input.start)ms,H)

Calculates the time span for an input value of the ‘DateRange’ (DateRange) type in the example on the left in three variants:

  • As a scalar (in milliseconds)

  • In the Time unit ‘milliseconds’ (ms)

  • Converted to the Time unit 'hours' (H)

NOTE For return values of the Relative date with time resolver, the expression for the time span in milliseconds should generally be (1ms+input.end-input.start), as the end value is defined 1ms too early by default.

entity

If the reference object in the context of the value resolver is a numerical value (with or without unit) or can be converted into a numerical value, this is available via the variable name entity.

convert(input,entity)

Converts the input value into the unit of a 'Unit number', which is available as a reference object.

$index$length

Current iteration index ($index) and scheduled number of iterations ($length) within a For each loop event action.

round(($index+1)/$length*100)

'Progress': Degree of processing with regard to the iterations when executing a loop (in percentage points).

NOTE◄ Depending on the context (e.g. depending on events or the selection in an overview), further variables can be automatically preset. However, these (like the entity variable) can only be used directly in a calculation expression in exceptional cases, as they mainly contain more complex data objects and not the numerical values expected in the label expression.

External context variables (storage) of the value resolver
(can be overriden by explicit assignments for the same variable name in the Inner context (see below) of the Calculate value value resolver).

In principle, any variable names can be used within labelling expressions. However, the restrictions listed on the right must be observed.

To prevent variable names such as '17+4' or '2022m3' from being calculated or parsed in the expression, they can be enclosed in single or double inverted commas in the expression. This also allows the use of spaces in the variable name. The escape character (e.g. for inverted commas as text characters) can also be used as a backslash within inverted commas.

IMPORTANT

  • The names of the preset constants e and pi (in lower case) are never resolved as variables in calculation expressions.

  • A calculation expression cannot directly access the value of variables in the context (storage) whose name exactly (incl. upper/lower case) matches the alias for a unit (see Units). The attempt to access a variable with the name b fails, for example, because this letter is considered an alias for the (Size unit 'bit') by default. An expression like 1+b therefore returns '2 bits'. Even inverted commas – such as 1+'b' – do not solve this problem!
    However, variables with alias names can be explicitly defined for the context of the value resolver (see next line). However, the unit concerned cannot then be used in the same calculation expression.

profit

profit2020

profit_2020

"1D"'1D'

"2020_profit"'2020_profit'

"2020-profit"'2020-profit'

"Profit 2020"'Profit 2020'

"Inbound/Outbound"'Inbound/Outbound'

"Sales 'AOB'"'Sales \'AOB\''

If the value of a variable is not a numerical value or a 'Unit number', an attempt is made to interpret its content as a number.

The string image is not automatically used for more complex data objects (e.g. values of dynamic enumerations). Only if the variable already contains a string like 1.5e2 as value, this can be read as a numerical value (1500).

If the conversion into a numerical value fails, then the value 0 (without unit) is used as the value of the variable instead.

Specially defined variables for the (inner) context of the value resolver.

Within the configuration of the value resolver, any number of explicit value assignments for existing or newly introduced variables (with the specified Variable name) can be added by clicking on the images/s/-95e2zf/9012/8yg2g7/_/images/icons/emoticons/add.svg icon, which only applies within the calculation expression.

Assignments for the context of the calculation do not change the value of variables already defined in the outer context. They are only temporarily overridden in the inner context, so that the 'outer values' cannot be included in the calculation.

IMPORTANT

  • The names of the preset constants e and pi (in lower case) are never resolved as variables in calculation expressions.

  • Assignments for Variable names that exactly match the alias for a unit (see Units) are possible. However, the corresponding alias cannot then be used in the same calculation expression as is usually the case. (see example on the right).

images/download/attachments/201666907/image-2025-3-5_15-6-43-version-1-modificationdate-1743580304077-api-v2.png

IMPORTANT◄ In order to output the calculation result in days, the conversion via convert(D*24-2.5H,D) cannot simply be used here, because D is temporarily considered as a long value without unit here and not as '1 day'!

The example on the right demonstrates how the alias D (for the Time unit 'day') is temporarily overridden by an assignment for the Variable name D, because in the special context the variable D is supposed to specify a certain 'number of days' (without unit). For a value of D = 1 the calculation expression gives concretely 1*24-2.5H = 22.5 (hours), where the alias H used in the minuend contributes the unit 'hours' for the result value.

Brackets






( <Expression> )







Pairs of brackets structure aggregates or delimit contained expressions from operators and operands (constants, variables, functions) specifically from each other to explicitly regulate the precedence between operators.

5+4*3^2

149 = 5+(4*3)²

5+4*(3^2)

41 = 5+4*(3²)

(5+4)*3^2

729 = (9*3)²

(5+4)*(3^2)

8 = 9 * 9

8^2/3

21,333... = 64/3

8^(2/3)

4 = cbrt(8^2)

sqrt((width)^2+(width/16*9)^2)

Diagonal of a 16:9 proportioned rectangle with width according to the width variable.

Operators

+

Addition or positive sign

1250kg + 2.5t

3750kg

-

Subtraction or negative sign

actual - target

Difference between actual and set point value in one variable each.

*

Multiplication

bottomLine * 1.25

Markup of 25% on a balance value in the variable bottomLine .

/

Division

profit/capita


EUR/CHF

'Profit per capita'.


'Exchange rate' for Swiss francs (CHF) in the sense of a bulk quotation (with 1 EUR as reference in 'local currency') based on the conversion factors in the enumeration Currency; see also convert()function

%

Modulo (remainder of the integer division)

totalPallets % 24

Number of pallets for a partial load, if the transport volume specified in the totalPallets variable is to be filled in containers with 24 pallet spaces each.

^

Exponentiation
(for square root in the example the function sqrt() would be alternatively suitable)

squaredErrors^0.5

Square root ('to the power of 1/2') of the 'sum of squared errors' aggregated in the variable squaredErrors.

Functions

abs(a)

Unsigned absolute value (math.: |a|)

abs(target-actual)

Absolute amount of the difference between target and actual values in variables.

sgn(a)

Signum value: 1 for (a>0), -1 for (a<0), 0 for (a=0)

sgn(target-actual)

'Sign value' of the difference between target and actual values in variables.

ceil(a)

Round up to the next highest integer

ceil(totalPallets)

Number of containers required (with 24 pallet spaces each) for the number of pallets specified in the totalPallets variable.

floor(a)

Round up to the next highest integer

floor(totalPallets/24)

Number of completely loaded containers (with 24 pallet spaces each) for the number of pallets specified in the totalPallets variable.

round(a)

Integer rounding (from 0.5 is rounded up)

round(profit/capita/1000)*1000

'Profit per capita' (from variables) rounded to 1000 currency units.

min(a,b)

Minimum of two values

min(actual,estimate)

The smaller value of two variables for 'actual' and 'estimate' of a quantity.

max(a,b)

Returns the larger of the two values

max(actual,estimate)

The larger value of two variables for 'actual' and 'estimate' of a quantity.

sqrt(a)

Square root, correspondingly: a^(1/2)

sqrt(squaredErrors)

Square root of the 'sum of squared errors' aggregated in the squaredErrors variable. 'Sum of squared errors'.

cbrt(a)

Cubic root, correspondingly: a^(1/3)

cbrt(totalVolume*0.75/pi)

Radius of a sphere with the volume specified in the totalVolume variable.

ln(a)

Natural logarithm of a

ln(maxNumber)/ln(2)

The binary logarithm of the value in the maxNumber variable.

log(a)

Base 10 logarithm

log(actual/target)

The 'order of magnitude' of the deviation between an actual and a target value (in variables) as a signed power of ten (e.g. -1 if the actual value is only one tenth of the target).

convert(a,b)


Convert value a to the unit of value b

convert(load,capacity)

Converts the freight (quantity) in the variable load into the unit of the capacity specification (capacity variable).

convert(totalCost,EUR)

Converts the total cost in the totalCost variable to the EUR Currency.

deg(a)

Convert radian angle a to angular degrees

deg(atan(-1))

-45 (°)
(atan() Supplies radians)

rad(a)

Convert degree angle a to radians

sin(rad(30))

0.5
(sin() Expects radians)

sin(a)

Sine value for radian angle a

sin(pi/2)

1.0
(pi/2 = 90°)

cos(a)

Cosine value for radian angle a

cos(pi/2)

0.0
(pi/2 = 90°)

tan(a)

Tangent for radian angle a

tan(pi/4)

1.0
(pi/4 = 45°)

asin(a)

Arc sine value (in radians) for a (sine value)

asin(1)/pi

0.5
(pi/2 = 90°)

acos(a)

Arc cosine value (in radians) for a (cosine value)

acos(0)/pi

0.5
(pi/2 = 90°)

atan(a)

Arc tangent value (in radians) for a (tangent value)

deg(atan(1))

45 (°)(atan()Supplies radians)

sinh(a)

Sine hyperbolic value for a

sinh(0)

0

cosh(a)

Consinus hyperbolic value for a

cosh(0)

1

tanh(a)

Tangent hyperbolic value for a

tanh(0)

0

Examples

Calculate a time span in days with decimals

Through Lobster Data Platform / Orchestration server, users can report particular operational incidents (faults, accidents, delays, etc.) by creating an entity of a specially defined type ('event'), classifying the incident by specific characteristics.

When creating the event entity, the system checks when an incident with a similar classification was last reported. If this search returns a match, a message indicates how much time (in days with one decimal) has passed since this incident.

Runtime example:

images/download/attachments/201666907/image-2025-3-5_16-13-42-version-1-modificationdate-1743580304030-api-v2.png

Configuration:

The event handling shown on the right reacts to the Triggering event (see Common action event) 'Create', which is triggered, among other things, when the user saves an entity in a data input form.

In the Validating rule, check type ensures that an entity of the 'Event' type is created.

As an Action on passed rule, the Search (Event action) is executed first, which searches for 'comparable' incidents among all events created so far. Details about the criteria for the search are irrelevant for the further workflow.

  • The search passes the first result, i.e. the last created event that meets all search criteria, into the variable latestIncident. For the sake of brevity, a check whether a match is present at all has been omitted here. This special case can be handled by If then else if necessary.

  • The Execute with event action defines the event found, if any, in the lastIncident variable as the reference object for subsequent actions:

    • The Show alert (Popup) event action, should indicate the time period since the event was found. The required calculation can be displayed directly within the Message using the Calculate value value resolver.

    • The main calculation step determines the difference between the current system time and the creation date of the found event in the input value. The UTC millisecond values (since 01.01.1970) are used for both time specifications. Corresponding specifications are determined via the now and created variables by value resolvers, which are described below.

    • Within the calculation expression the long value difference now-created is first declared as milliseconds (ms), in order to convert this then over the convert()function into the Time unit 'day' (D). The time span in days is multiplied by 10, rounded down to an integer and then divided by 10 again, which gives a numerical value in days with one decimal as the return value.

    • The following text concatenation does a bit of cosmetic work to optimize the appearance of the output, so that instead of the internal name for the unit (day), its alias (D) is output in lowercase letters.

images/download/attachments/201666907/image-2025-3-5_16-9-36-version-1-modificationdate-1743580304043-api-v2.png

On the right are details about the configuration of the Calculate value value resolver:

  • The first variable with Variable name now reads the millisecond value of the current system time, which is returned by the Relative date with time value resolver per Type 'Now'. Since we only include the UTC milliseconds in the 'Date value' (dateValue) Long property in the calculation, the Time Zone is completely irrelevant here.

  • The second created variable is read from the 'Created' (created) property of the input value, i.e. the event entity. This is the date type 'Timestamp', from which the UTC milliseconds can be determined directly via the Input object (type safe) value resolver via a conversion to Long.


NOTE◄ The Timestamp data type cannot be interpreted directly as a numerical value. Otherwise you could access it in the expression via input.created without a diversion via a variable.


NOTE◄The conversion of the millisecond difference to days relies on conversion rules in the dynamic enumeration Time unit, which are not calendar-specific operations, but only 'mediate' between the time units millisecond (ms) and day (D). Corresponding conversions could also be handled here directly and without conversion by dividing the milliseconds by 86,400,000. That's the number of milliseconds in a day.

However, the convert()function makes it comparatively easy to convert the output to other target time units if necessary, by using their alias (such as the H for hours) instead of D.

images/download/attachments/201666907/image-2025-3-5_16-10-58-version-1-modificationdate-1743580304040-api-v2.png

Calculating the package volume from length x width x height (with variable length unit)

For a package, the dimensions 'length', 'width' and 'height' are available in numerical fields, whose Length unit can be selected by the user – if necessary differently for each dimension.

From this information, the volume of the cuboid idealized package is calculated in a selectable Volume unit within an event handling and written to the Volume variable as a value of the 'Unit number' type.

To specify the desired Volume unit, it is pre-assigned to the Volume variable so that it already contains a value such as '0 liters' or '0 gallons' before the calculation.

Configuration:

The suitably initialized target variable Volume (with the default for the target Volume unit) is at the beginning of a concatenation of value resolvers as shown on the right. For our example, '0 liters' should be preset.

  • The Calculate value value resolver receives the value of the preset Volume variable as input value, which can be accessed by the calculation expression via the input name. The nested calculation is described below 'from the inside out' step by step:

    • On the 'innermost' level, the length specifications in the variables length, width and height are converted into an arbitrarily chosen uniform length unit ('meter' with alias m). This is done by the convert()function with the target unit m.

    • Formally, a product of three quantities with the same unit is also assigned this unit in the result. In this case, the converted lengths result in a numerical value that 'means' cubic meters, but is technically shown as 'meters'. This does not make much sense. But due to the previously executed conversion of the input data into the uniform unit (m), we at least know that the numerical value is evaluated as 'cubic meters' (m3).

    • In line 6 selected in the screenshot, the product of the 'length' is multiplied by the alias m3. Within the four-part product – from the system's point of view – data in non-compatible units (length in m vs. volume in m3) are offset. Since there is no conversion rule for this, the product is shown as a scalar quantity (without unit).

    • The scalar quantity, whose numerical value (as we know) specifies cubic meters, is now also formally converted into the unit m3 by the surrounding convert()function. This conversion would fail for a specification in m .

    • In the outermost level, a real conversion from the formally declared 'cubic meters' (m3) to the desired target volume unit can now finally take place. For this, the reference to the input value (input) is sufficient, whereby only its unit but not its value is taken into account.

  • The concatenated Store value as variable value resolver stores the result here directly into the Volume variable, so that the complete value resolver chain can be used directly in a Show alert (Popup) event action, for example. Instead, a Set value event action could also be used to write the calculated 'Unit number' into the variables.

images/download/attachments/201666907/image-2025-3-5_16-3-25-version-1-modificationdate-1743580304050-api-v2.png

The screenshot on the right shows how the assignment of the variables for the input data length, width and height was solved in our example for test purposes:

  • For the length variable, a static 'decimal number' (with the value 1,2) was assigned here. The explicit conversion in the calculation expression ensures that this actually scalar information is interpreted as meter (m).

NOTE◄ The decimal separator ‘comma’ only affects the representation in the input context. 1.2 would have to be written directly in the calculation expression to achieve the same result.

  • The width variable is assigned a static value in centimeters (cm). This works conveniently by using a Calculate value value resolver with a static expression (80cm).

  • The height variable is assigned a static specification in feet (ft). Again, a Calculate value value resolver with a static expression (3.33ft) is used.

For operational practice, assigning static values for the three variables does not make sense. Assuming that the information for the three dimensions of the package exists, for example, as fields (or attributes) of a common data object, this could be defined as a reference object in the context of the value explorer by an Execute with event action, in order to then access it in the assignments for the length, width , and height variables via the entity variable. For example, in the context of an unspecified entity, accessing an itemLength field for assignment to the length variable would look as follows:

images/download/attachments/201666907/image-2025-3-5_16-5-59-version-1-modificationdate-1743580304045-api-v2.png

images/download/attachments/201666907/image-2025-3-5_16-4-58-version-1-modificationdate-1743580304047-api-v2.png

NOTE◄ It is not described here how the length, width and height variables – apart from the test with static values – are actually supplied with values.

Typically, Object property resolvers would be used here, which assign suitable values from the external reference object to the variables.

If several values are read from the same reference object and are 'calculated' directly, it would actually make sense to use the reference object as the input value and to address the individual fields in the calculation expression via the input variable.

Configuration variant:

The screenshot on the right shows a value resolver chain that is supplied directly with the data object for the package as an input value (here: as a reference object). The dimensions to be calculated should be available in the ‘length’ (length) , ‘width’ (width) and 'height' (height) fields, each as a ‘Unit number’.

The calculation expression is basically structured as described above, but with the following adjustments:

  • The dimensions are now accessed via data field paths for the input (in lines 3-5) variable.

  • The target unit for the conversion to the target value (see line 8) is now no longer taken from the input but from the Volume variable, which was originally still the input.

NOTE◄ The explicit ‘assignment’ of the numerical input values to variables is completely omitted here. However, this access only works as long as the read data is available directly as numerical values (here: with a unit) in the input.

NOTE◄ A Create instance with values resolver can be added as the start of the value resolver chain for tests, for example, in order to provide a ‘package’ as a client object.

images/download/attachments/201666907/image-2025-4-3_13-32-5-version-1-modificationdate-1743679925760-api-v2.png

Evaluate the 'range' of the logged-in user account in an association criterion

Users are classified using a 'range' key figure, which is defined as the product of the number of Roles and Company accounts that can be selected at login.

An association criterion should apply if the ‘range’ of a user is at least 3.

Configuration:

In the context of a With rule that defines the evaluated user as a reference object (e.g. the User of session), the criterion shown in the screenshot on the right is checked:

  • A Check type first ensures that there is a ‘user’ as a reference object and (with regard to the User of session, possibly decisive) not a guest user.

  • Within an AND Junction, an Entity property rule follows to determine whether the 'range' calculated as the check value (left) is in the desired relation (≥) to the compare value (right) using the Compare with matcher type.

    • The check value can be determined very easily with the Calculate value resolver, as the required input data can be addressed directly in the input value (input). The length field shows the number of entries in the parent list field of the user account. The calculation expression uses this information for the ‘Companies’ (companies) and ‘Roles’ (roles) list fields of the user account.

    • The compare value is defined here as static Long value 3.

NOTE◄ The fact that the value in the Object property length here is only based on an internal calculation (for ‘lists’) and not on a persisted database field of the user is irrelevant for access via the data field path.

images/download/attachments/201666907/image-2025-4-3_13-33-53-version-1-modificationdate-1743680033644-api-v2.png

Calculations with data from a map

Access via data field paths for details from a complex input value is also possible when a map is involved.

For the following example, a map is available in a sales variable, in which sales figures (number of units) for the completed quarters of the current year have been written using systematically named key values (‘Q1’, ‘Q2’, “Q3”, ‘Q4’).

The sum of all quarters for the current status is to be calculated and written to the map as an additional value under the key ‘TOTAL’.

Configuration:

The screenshot on the right shows an Execute with event action whose action block uses the map in the sales Variable as a temporary reference object.

Calculation and value assignment can be handled within the same Set value event action:

  • A Map item is identified as the target for the value assignment (left) via the Key TOTAL determined by static Text (Statische Werte. Whether this already contains a value or even exists is irrelevant.

  • The value to be assigned (right) is determined using the Calculate value resolver, for which the map (sales) in the reference object is the input value (input). The calculation expression can simply retrieve all potentially relevant ‘keys’ in the map in the input value (input) and add them up. The value 0 is used for keys that are not found.

images/download/attachments/201666907/image-2025-4-3_13-27-55-version-1-modificationdate-1743679675227-api-v2.png

Calculations with data from lists

Access to list values via index

If the input value is a list or contains list values, the calculation expression can access individual list values via their absolute index position.

  • The index always starts at 0.

    • The first list value of a list of numerical values available as an input value can therefore be addressed as input.0 in the calculation expression.

  • If a list value is a complex object, the data field path can be continued after the index value in order to further resolve its structure.

    • The expression input.2.maxCapacity reads the value of the maxCapacity field of an object that is the third entry in the list provided as an input value (if available).


IMPORTANT◄ In contrast to the context of a form, where the get (Read value from data field) function enables access to list values via a variable index value, this is not possible here. Index values can only be defined statically and absolutely in the calculation expression.

A Custom entity type ‘Aircraft’ (Aircraft) lists areas of an aircraft in the list field, which can be further subdivided via another list field zones.

By convention, each relevant aircraft can be described by a maximum of four loading areas (areas), to each of which 1-2 zones (zones) are assigned.

A ‘load weight’ (weight) can be assigned to each zone via the0 weight field. At the same time, a fictitious ‘lever arm’ (arm) is specified for each zone, which is used to calculate the moment depending on the payload.

Before the aircraft takes off, it must be checked whether the total mass and the total moment are within the permissible operating range, taking into account the actual load and fuelling (here: modelled via the zones).

The following configuration shows how the total torque can be calculated for an Aircraft object defined in an acft variable.

Configuration:

The screenshot on the right shows a value resolver chain (see Chained resolver), which can be used to determine the ‘total moment’, e.g. as a message in a Show alert event action:

  • The Variable value resolver provides a specific Aircraft entity that contains all the raw data for a weight & balance determination.

  • The linked Calculate value resolver receives the complete Aircraft object as an input value (input) and can process the maximum definable 4 areas (areas), each with 2 zones (zones), in the calculation expression in an overall approach for the ‘total torque’.

    IMPORTANT◄ The value 0 is taken into account for non-parameterised areas and zones, which does not affect this specific calculation process.

  • The total result of the calculated ‘product sum’ (weight x lever arm) is written to the variable totalMoment as ‘total moment’ via a store Store value as variable resolver.

images/download/attachments/201666907/image-2025-4-3_13-25-29-version-1-modificationdate-1743679529335-api-v2.png

NOTE◄ This example is intended to show how index access for list values can be performed for calculations with a defined (or at least finite) number of list values. Calculations for lists with variable length always enable a For each loop event action and – in special cases – the execution of a calculation (via value resolver, e.g. Calculate value or Simple calculation (+,-,*,/,%)) in a Collect values resolver.