Example custom functions

Making sure percentages add up in a Q&A

ClauseBase’s standard Q&A conditions functionality let you easily check whether a certain number-answer is in a certain range — e.g., higher than 40 and lower than 100. However, the standard conditions do not allow you to create conditions that combine various answers together.

For example, assume you are making an employment contract for situations where employees can divide their time between three different positions (e.g., sales, marketing and IT). Obviously, for a full-time position, the percentages need to add up to 100% — if not, then some warning needs to be shown.

Questions to create
Clojure code
Showing the current total
  • Create three different questions with number (integer) answers. Assign those questions the identifiers f1, f2 and f3 respectively in their options.
  • Create a warning question with a content such as “Warning: the percentages do not add up to 100%”.

Insert the following Clojure code in the condition attached to the warning-question, so that the warning-question will only be shown when the result of the Clojure-code is true.

(defn value-or-0 [id] 
    (or (answer id) 0))

(not= 100 
      (+ (value-or-0 "f1") (value-or-0 "f2") (value-or-0 "f3")))

We first define a Clojure-function that fetches the answer of the question with the specified identifier. If that answer happens to be nil — which would be the case when the end-user has not yet filled in any value — we return 0, otherwise we return the answer.

We then add the three percentages, and check whether they add up to exactly 100. If so, the result will be false (so that the warning will not be shown); otherwise the result will be true, so that the warning will indeed be shown.

When none of the three percentages is filled in, the warning is also shown. It is probably advisable to only start showing the warning when at least one of the three percentages if filled in.

A first way to solve this, is by adding a subgroup of non-Clojure subconditions:

A second way to solve it, is by adapting the Clojure-code as follows:

(defn value-or-0 [id] 
    (or (answer id) 0))

(and (or (answer "f1") (answer "f2") (answer "f3"))
     (not= 100 
       (+ (value-or-0 "f1") (value-or-0 "f2") (value-or-0 "f3"))))

This code specifies that two conditions must be met for the warning-question to be shown:

  1. at least one of the percentages-questions must have its answer filled in
  2. all three percentages together must not be equal to 100

Instead of showing a static warning (“Warning: the percentages do not add up to 100%”), it is more helpful to show the current total amount.

To do so, show the options of the warning-question, click on the button and add the following Clojure code:

(defn value-or-0 [id] 
    (or (answer id) 0))

(defn total []
    (+ (value-or-0 "f1") (value-or-0 "f2") (value-or-0 "f3")))

(assoc question :title 
       {:en (str "Warning: the percentages do not add up to 100% " 
                 "(current total: " (total) "%)")})

To change the title of the warning, we assoc a new value in var question. (This var is predefined by ClauseBase’s Clojure runtime when customising questions.)

If other languages besides English would be required, then the specified map should be extended — e.g. with a string for French (:fr) or Dutch (:nl).

By the way, because the function value-or-0 is now used both in this custom function and in the previous Clojure-code for calculating the warning’s visibility condition, it could be useful to move this function to the central repository, and replace the calls — e.g., instead of (value-or-0 "f1") we would get (call "value-or-0", "f1"). The contents of the central repository function can then simply be (or (answer $1) 0) — the $1 refers to the first parameter that gets passed into this function, which would be "f1" in the given example.

Was this article helpful?
ClauseBase API
Custom functions