Logo

Scripting Language

Scripting Language #

The scripting language is a language created especially for programming custom validations in data capture operations. For each type of data defined in the Data Model, it is possible to generate a custom verification when capturing the data from a client. For example, simple (like the length of a user name) or more complex things (like the validation digit and format of an Uruguayan identity card) can be verified.

Example - Validation of user name length:

function validateUserName (value) do
  if len(value) < 6 or len(value) > 20 then
    return "User name should be between 6 and 20 characters"
  end
end
addValidations(validateUserName)

In the image below we can see the work environment and the language editor:

Preview Scripting Language

Among the distinguishing features of the language, it is not necessary to use ; to close lines of code. This applies to the assignment of variables, as well as to the rest of the statements and commands. Instead, you can directly use a line break.

Variables #

The scripting language supports variables of type number, text, and boolean (logical values). They do not need to be declared beforehand but can be assigned directly. Variable names admit styles such as CamelCase or snake_case if you wish. Both apply to phrases or compound words as follows:

  • CamelCase: capitalization is used on the first letter of each word to correctly identify them, although it is possible to exclude this rule on the first word. As examples, we can use MultipleWordVariable or MultipleWordVariable.

  • snake_case: words are separated using underscores, such as multiple_word_variable.

Numbers #

You can assign whole numbers or decimals to variables, and even numerical operations.

Examples:

var1 = 35.28745
var2 = 77 + 48/3

Text #

If you assign text strings to variables, they need to be enclosed in double quotation marks (""). You can also use quotes literally within the string by employing a backslash \ to escape them. This way, the language will consider them as part of the string instead of making them content delimiters.

Examples:

stringVar = "This is a string"
stringVarWithQuotes = "This is a quoted \"String\""

Multi-line text #

Multi-line text can be assigned to variables as illustrated below:

Example:

multiLineText = "Multi Line
                 Text"

Logical values #

The true and false keywords are reserved as Boolean values. As such, you can assign them to variables in the same fashion as above.

Examples:

varBoolTrue = true
varBoolFalse = false

Functions #

Function outputs can be assigned to variables as well:

Example:

functionVar = fncall(127)

Variable scope #

The scope of a variable determines where you can use it in the program:

  • global (outside of function statements), or
  • internal to a function.

In the first case, if changes are made within a function they will only apply inside that context and not globally. On the other hand, the internal variables of the functions only exist within them.

Comments #

The # character is used to make comments, either at the beginning of an empty line or after one that contains code.

Examples:

# This is a comment.
balance = 224.22 # This is another comment.

The hashtag character is used to produce comments - either at the beginning of an empty line or after one that contains code. The entire first line of the code above is a comment, while the one in the second line begins after balance = 224.22.

It is important to note that the only way to make multi-line comments is to place the # on each line you wish to comment out.

Arithmetic Operators #

The language supports the classic arithmetic operators throughout the code. The multiplication and division operators take precedence over addition and subtraction.

Available operators:

DescriptionOperator
Sum+
Subtraction-
Multiplication*
Division/

It is not possible to use parentheses to group operations.

Concatenation #

The sum operator allows you to concatenate two or more text strings with each other, or text with numbers.

Examples:

concatText = "My name is " + "Ricardo"
outstandingNumber = 2487224
textWithNumber = "I'm fascinated by the number " + outstandingNumber

In these examples, concatText and textWithNumber contain My name is Ricardo and I'm fascinated by the number 2487224, respectively.

Comparison Operators #

By using the following operators, you can generate Boolean variables by making comparisons. They can also be used in conditional (if-then-else) or loop (while) flow control structures.

DescriptionComparison operator
Equal to==
Not equal to!=
Less than<
Less than or equal to<=
Greater than>
Greater than or equal to>=

Examples:

var1 = 8
var2 = 15
comp1 = var1 < var2
var3 = 10
var4 = 15
comp2 = var3 == var4

Since 8 is less than 15, comp1 evaluates to true. Conversely, comp2 is false because 10 is not equal to 15.

Function Declarations #

The first alternative to declare functions takes the following form. The * symbol indicates that the argument in question is optional:

function <ident>(<arg1>*, <arg2>*) do
     <body*>
    return*
end

where:

  • <ident> is the function name.
  • (<arg1>, <arg2>) are the input arguments. You can use as many arguments as you like by separating them with commas.
  • <body> represents the statements that make up the function.
  • return defines the function’s output. It can consist of both variables (that have a data type or function associated with them) and numbers, booleans or text. It is also valid to omit this statement and not to return anything.

Example:

function fnWithArgs(value1, value2, value3) do
  aux = value1 + value2*value3
  return "Function returns: " + aux
end

Another alternative to declaring a function is as follows:

ident = function(<arg>*) do
 <body*>
 return*
end

In this case, we declare the function and assign its return value to the variable named ident in the same step.

Functions That Accept Other Functions as Input #

A function can accept another as a possible input argument.

Example:

function mean(value1, value2) do
  aux = value1 + value2
  return aux/2
end
function main(value1, value2, func1) do
  result = func1(value1, value2)
  return result
end
main(15, 10, mean)  # function call with another function as an argument

In the code above, the main function expects three arguments. The first two (value1 and value2) are normal values, and the remaining one is a function. When it is invoked on the last line, the two values are processed by mean.

Functions Without Parameters #

It is possible to declare a function without arguments by simply placing () after the function identifier.

Example:

function fnWithoutArgs() do
  return "Global Error"
end

Functions That Do Not Return Anything #

If you use a function to execute a series of statements and do not need to return a value, you must omit the return command at the end.

Example:

function noReturn (val1) do
  if val1 < 48 then
    loginfo(val1)
  end
end

Control Structures #

If-Then-Else #

It is possible to use a conditional structure of type if-then-else to implement flow control. In its most generic form, it is as follows:

if <exp> <comp> <expr> then
     <body>*
else
     <body>*
end

where you can omit the else keyword if you do not need to consider an alternate course of action. In that case, the above structure is reduced to

if <exp> <comp> <expr> then
     <body>*
end

To execute two or more statements inside a given if or else block, place them in separate lines one after the other.

<exp> <comp> <expr> is a comparison between two expressions. <comp> can be any of the comparison operators listed under Comparison operators. If the condition is met, the statement(s) after then are executed. Otherwise, the script will run the else block (if it exists).

Example: If-Then-Else with Else

function conditional (value1, value2) do
  if value1 >= value2 then
    return "value1 is greater or equal than value2"
  else
    return "value1 is less than value2"
  end
end

Example: If-Then-Else without Else (If-Then)

function conditional_without_else (value) do
    if value1 == 8 then
      result = value*15
    end
    return result
end

Example: If-Then-Else with boolean condition

It is valid to replace the condition <exp> <comp> <expr> directly by a boolean variable <bool>. As it is expected, the sentences inside then will be executed if <bool> is true, or those inside else (if present) otherwise.

The general format is as follows, where <stm*> represents one or more statements:

if <bool> then
  <stm*>
else
  <stm*>
end

A more real example is found below:

function condBool(value) do
  bool1 = value == 8
  if bool1 then
    return "Input equals 8"
  else
    return "Input does not equal 8"
  end
end

Example: If-Then-Else with logical operators between conditions

The and and or logical operators can be placed between two or more conditions. On the other hand, the logical not() allows us to negate one condition.

The use of the and operator expects that all the individual conditions must be true to meet the entire if expression. On the other hand, the or operator only requires at least one of the individual conditions to evaluate to true to accomplish the same goal.

Example:

function condLogic(value1, value2, value3, value4) do
  if value1 != value2 and value3 < value4 then
    return "Yeah!"
  end
  if not(value1 != value2) then
    return "Value1 is equal to Value2"
  end
end

The function above will return Yeah! when value1 is not equal to value2 and value4 is greater than value3. Next, the script will check whether value1 and value2 are not equal, and will output Value1 is equal to Value2 if they are identical.

While #

The while loop is used to iterate over a group of statements as long as a given condition evaluates to true. Its basic syntax is as follows:

while <expr> do
  <body>
end

where <expr> is a logical expression having the same format as in the if-then-else structure. For example:

function iterate1 (value) do
  while value < 150 do
    value = value*2
  end
end

Inside of the iterate1 function, the loop will continue to multiply value (initially an argument to the function) by 2 while the result is less than 150.

Example: While with logical operators between conditions

The use of the and, or y not() logical operators is allowed in the same fashion as with if-then-else:

function iterate2 (value1, value2) do
  while value1 < 150 and value2 < 200 do
    value1 = value1+10
    value2 = value2+40
  end
end

where value1 and value2 increment their values by 10 and 40 units in each iteration. This process continues until they become greater than or equal to 150 or 200, respectively.

Data Structures #

Arrays #

An array is a data structure that consists of a finite, sorted collection of items. The scripting language includes a series of functions that allow you to create and manipulate unidimensional arrays.

It is important to clarify that an array can hold any type of data (numbers, text, or booleans) inside of it.

array() #

This function creates a new array. To do so, use arr = array(), where arr is defined as an array.

aset(arr, ind, data) #

Inserts an item named data in arr at the position given by ind.

aget(arr, ind) #

Retrieves the item found in arr at index ind.

alen(arr) #

Returns the length of arr (number of items).

Examples with arrays #

In the following code block, we create an array and then add items to it. Next, we find out the array length. Finally, we retrieve an element from the array.

Example 1:

arreg = array()
aset(arreg,0,25)
aset(arreg,1,454)
aset(arreg,2,422.25)
arrayLength = alen(arreg)
value = aget(arreg,2)

The value variable holds the value 422.25 that was previously stored at position 2 inside the array. On the other hand, arrayLength equals 3 since that is the number of items in the array.

Example 2:

arrText = array()
aset(arrText, 0, "Braulio")
aset(arrText, 1, "Hector")
aset(arrText, 2, "Hugo")
arrayLength = alen(arrText)
value = aget(arrText, 0)

In this case, value and arrayLength contain the values Braulio and 3, respectively.

Dictionaries #

The scripting language includes a series of functions that allow you to create and manipulate dictionaries. A dictionary is a structure that consists of a set of key/value pairs with the requirement that the keys are unique.

dict() #

This function creates a new dictionary. To do that, use dictionary = dict().

set(dictionary, key, data) #

Inserts a key/value pair composed of key and data in dictionary.

get(dictionary, key) #

Returns the value associated with key from dictionary.

Examples With Dictionaries #

The following block illustrates how to create a dictionary, how to insert key/value pairs into it, and how to retrieve them.

infoPerson = dict()
set(infoPerson, "name", "Bob")
set(infoPerson, "ID", 8504234)
set(infoPerson, "job", "Sales manager")
set(infoPerson, "car", "BMW")
car1 = get(infoPerson,"car")

After running the code shown above, the variable named car1 contains the value BMW.

Mathematical Functions #

The scripting language has several built-in mathematical functions that are described below.

abs(value) #

Returns the absolute value of value.

round(value) #

Rounds value following standard rounding rules.

ceil(value) #

Returns the closest integer (greater than or equal to value).

floor(value) #

Returns the closest integer (less than or equal to value).

max(value1, value2) #

Takes one or more arguments and returns the maximum value.

min(value1, value2) #

Takes one or more arguments and returns the minimum value.

mod(value1, value2) #

Returns the remainder of the integer division between value1 and value2 (value1/value2).

random() #

Returns a random value between 0 and 1.

Text Functions #

regexp(pattern) #

This function creates an object of type regular expression to search for the occurrences of a given pattern inside of a text.

Example:

patternLettersOrNumbers = regexp("[A-Za-z0-9ñÑ]")

In summary, patternLettersOrNumbers will match one or more lowercase or uppercase letters (including the Spanish ñ). Said another way, this regular expression will match any alphanumeric character.

val(string) #

Converts string into its equivalent numeric value only if string consists of digits only.

substring(string, arg1, arg2) #

Extracts characters from string starting with the position given by arg1 (inclusive) to arg2 (exclusive). Since arg2 is optional, this function can extract everything between arg1 until the end of the string.

While manipulating characters in a string using this function, both arg1 y arg2 are zero-index based.

Example:

If you use

var1 = substring("Complete string",2)

var1 will take the value mplete string.

Example:

var1 = substring("Complete string",2,11)

In this case, var1 stores mplete str.

trim(string) #

Removes blank spaces from both ends of the text given by string.

Example:

text = "      text with lots of blank spaces             "
text2 = trim(text)

As result, text2 will equal text with lots of blank spaces (with no spaces at all).

replace(string, arg1, arg2) #

Replaces arg1 with arg2 in string, where arg1 can be any text or regular expression. If the former, the change is made only in the first occurrence of arg1. Otherwise, the modification will be effective in all matches of the patter inside the string.

Example (use as text):

text = "it is remarkable to remember that the last meeting was remarkable"
out = replace(string, "remarkable", "important")

After executing the statements above, out will contain it is important to remember that the last meeting was remarkable.

Example (use as regular expression):

expReg = regexp("she\w{2}")
string = "She sells seashells on the seashore. The shells she sells are surely seashells. So, if she sells shells on the seashore, I'm sure she sells seashore shells."
out = replace(string, expReg, "star")

In this instance, out will store the string She sells seastars on the seashore. The stars she sells are surely seastars. So, if she sells stars on the seashore, I’m sure she sells seashore stars..

match(string, arg) #

Returns a boolean value (true or false) based on the presence of arg inside of string.

len(string) #

Returns the number of characters in the text given by string.

Other Functions #

loginfo(arg) #

Prints the content of arg in the browser console.

rest(method, host, headers, params) #

Allows performing HTTP requests to a web service. The input parameters are the following:

ParameterData typeObservation
methodTextHTTP request method (GET, POST, or PUT)
hostTextDestination host URL
headersDictionaryHeader to be passed to the web service1
paramsDictionaryOther structures to be passed to the web service2

The function returns a dictionary with the following keys:

KeyData typeDescription
bodyTextResponse body returned by the web service
statusTextHTTP response code (request result)

Example:

headers = dict()
params = dict()
host = "https://google.com"
set(headers, "content-type", "application/soap+xml")
set(params, "body", "")
response = rest("GET", host, headers, params)
status = get(response, "status")
bodyReturn = get(response, "body")

If the request succeeds, status will store 200 whereas bodyReturn will contain the body of response.

Code Execution Flow #

The first step in the code design should consist of declaring the functions (and optional global variables) that will be used later. It is important to remember that calling an undefined function will lead to errors.

The functions called in the code will be executed immediately when entering the funnel. If you need to verify a data capture control at this point, you must invoke the built-in function addValidations(f) with the validation function f as an argument.

The addValidations(f) Function #

This function links the data capture field to be validated with the code using f as the starting point of the validation. Since addValidations can be invoked several times in the same program, it is possible to perform several independent verifications for the same field.

As it is to be expected, addValidations(f) should be called after declaring f and any other functions used by the latter.

A few points to keep in mind:

  • The input argument of f is the value that will be entered in the field under verification.
  • The return value of f will be the message that will be displayed in case of an error in the validation.
  • If the validation was successful, it is not necessary to return any message. For that reason, you can omit the return command in that case.

To illustrate, let us consider the following example:

function validateRange (value) do
  if value > 8 then
    return "Valor de entrada debe ser menor o igual a 8"
  end
end
addValidations(validateRange)

where value is the number that is entered in the data capture form. If it is greater than 8, an error message will be displayed (Valor de entrada debe ser menor o igual a 8). This means it is expecting a number that is less than or equal to 8 to pass the test:

Error validation message

In the case that value is less than or equal to 8, the data capture will succeed and allow to progress to the next funnel step when the customer clicks Submit.

Multiple Validations on a Single Field #

As explained above, addValidations() can be invoked several times to perform the same number of verifications.

Example:

function validateRange (value) do
  if value > 8 then
    return "Input value must be less than or equal to 8"
  end
end

function validateNumber (value) do
  if match(value,regexp("[^0-9]")) then
    return "Input value can only contain numbers"
  end
end

addValidations(validateRange)
addValidations(validateNumber)

Two validations are performed in this case: 1) input value must be a number, and 2) it should be less than or equal to 8. If one of these conditions are not met, a message will be shown to highlight the error.

Code Examples for Commom Validation Cases #

Basic Examples #

Validation of Number of Characters in a Text Field #

The following code block uses a function called checkDataLength to verify that the number of characters in a text field is greater than 6 but less than 20:

function checkDataLength(value) do
    value = trim(value)
    if len(value) < 6 or len(value) > 20 then
        return "Field length must be between 6 and 20 characters"
    end
end
addValidations(checkDataLength)

As expected, the function is called when it is passed as an argument to addValidations.

Validation of Character Types in Text Fields #

In the example below, checkChars will validate that the text field only contains letters and/or numbers.

function checkChars(value) do
    value = trim(value)
    if match(value,regexp("[^A-Za-z0-9ñÑ]")) then
        return "Only letters and numbers are allowed on this field"
    end
end
addValidations(checkChars)

Date Validation #

The scripting language also allows validating that a given date is after another. To accomplish this goal, the input date should follow the mm/dd/yyyy or mm-dd-yyyy formats.

function checkDate(value) do
  value = trim(value)
  month = val(substring(value,0,2))
  day = val(substring(value,3,5))
  year = val(substring(value,6,10))
  if year == 2002 and month == 6 and day >= 23 then
    return "Only dates before 6/23/2002 are accepted"
  end
  if year == 2002 and month > 6 then
    return "Only dates before 6/23/2002 are accepted"
  end
  if year > 2002 then
    return "Only dates before 6/23/2002 are accepted"
  end
end
addValidations(checkDate)

In the example above, only dates after June 23, 2002 are considered valid.

Advanced Examples #

Validation of Uruguayan ID Number #

function normalize_ci(value) do
    value = trim(value)
    loginfo("trim " + value)
    value = replace(value,regexp("[\.-]"),"")
    while len(value) < 8 do
        value = "0" + value
    end
    return value
end
function validate_uy_ci (value) do
    i = 0 
    a = 0 
    digit = 0
    value = normalize_ci(value)
    v = substring(value,0,7)
    dv = substring(value,7)
    while i < 7 do
        vl = val(substring("2987634",i,i+1)) * val(substring(v,i,i+1))
        a = a + vl
        i=i+1
    end
    if mod(a,10) == 0 then
        digit = 0
    else
        digit = 10 - mod(a,10)
    end
    return digit == dv
end
function validations (value) do
    if not(validate_uy_ci(value)) then
        return "No es una cédula de identidad válida"
    end
end
addValidations(validations)

Username Validation #

The following example validates if a given username has the correct length (between 6 and 20 characters), if it only contains letters and/or numbers, and if it already exists in the database. This last check is done by querying a web service.

function checkUsernameLength(value) do
    value = trim(value)
    if len(value) < 6 or len(value) > 20 then
        return "Username must be between 6 and 20 characters long"
    end
end
function checkUsernameChars(value) do
    value = trim(value)
    if match(value,regexp("[^A-Za-z0-9ñÑ]")) then
        return "Username can only contain letters and numbers"
    end
end
function checkUsernameExists(value) do
    headers = dict()
    set(headers,"content-type","application/soap+xml")
    params = dict()
    host = "https://knrioscript.free.beeceptor.com"
    body = ""
    set(params,"body",body)
    response = rest("GET",host,headers,params)
    useduser = get(response,"body")
    statusresponse = get(response,"status")
    loginfo(statusresponse)
    if match(useduser,value) then
        return "The username is not available. Please choose a different one"
    end
end
addValidations(checkUsernameLength)
addValidations(checkUsernameChars)
addValidations(checkUsernameExists)