<commit_before># Advance Example

## Distributed Process

In the previous example, the sub-processes (Process 1, Process 2, and Process 3) was executed in a single computer.

Chimera-framework can also run in distributed scenario. Suppose Process 1 should be run in the server, and Process 2 should run in the client, we should divide the process into 4 steps.


![chimera-example-distributed](doc/chimera-example-distributed.png)

Before we dive into the steps, we should prepare two more files.

```yaml
# server.yaml
(a , b) −> php tests/add.php −> c
```

`server.yaml` contains only a single process (`tests/add.php`). It takes `a` and `b` as inputs, and return `c` as output. Executing `chimera server.yaml 4 5` will return `9`.

```yaml
# process.yaml
ins: a, b, server
out: e
verbose : true
series :
    − parallel :
        # Process 1
        − (server, 'server.yaml', a, b)−> chimera−send −> c
        # Process 2
        − (a, b) −> php programs/add.php −> c
    # Process 3
    − (c, d) −> node programs/add.js −> e
```

This YAML chain file is basically similar to our previous example. The only difference is on Process 1 definition. This process takes 4 inputs. The first one is server address, the second one is server's YAML chain, and the last two inputs will be sent `server.yaml`'.

`chimera-send` is a utility to execute YAML chain file in other computer. Its first two parameters are `server address` and `server YAML chain file` respectively.

After preparing the files, we should proceed with these 4 steps:


* __Server side preparation__: In the server side, we need to provide:
    - `tests/add.php`
    - `server.yaml`

* __Server side execution__: After server preparation completed, we need to serve `server.yaml`, so that it is accessible from the network. In order to do this, we can execute `chimera-serve`, a utility to serve chains in the server:

```sh
chimera-serve
```

* __Client side preparation__: In the client side, we need to provide:
    - `tests/add.php`
    - `tests/add.js`
    - `process.yaml`

* __Client side execution__: After client preparation completed, we can then execute:

```sh
chimera process.yaml 4 5 http://server-address.com:3000
```

## Shorthand

Let's look at this example:

```yaml
# filename: add.yaml
ins: a, b
out: c
command: node add.js
```

You can invoke the chain by performing `chimera add.yaml 5 6`. Assuming you `add.js` works correctly, you should see `11` as result.
If you don't define `out` element, `_ans` will be used by default.

Chimera also provide some shorthand for your convenience. The above example can also be written as:


```yaml
# Now, we put ins and out into the command, separated by ->
# The format is: [input] -> [process] -> output
command: (a,b) -> node add.js -> c
```

if not specified, the out parameter is default to `_ans`

```yaml
ins: a, b
command: node add.js
```

You can also write the process as:
```yaml
command: (a, b) -> node add.js
```

or even:

```yaml
(a, b) -> node add.js
```

In some situation, your process might be so simple that you only need a single line javascript arrow function instead of a fully stand alone program. In that case, you can do this:

```yaml
(a, b) -> (x,y)=>{return parseFloat(x)+parseFloat(y)}
```

For more comprehensive information regarding anonymous javascript arrow function, please visit [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

## Process control (branch and loop)

Sometime your process contains several simple logic (i.e: loop and branch). Please look at this example:

```yaml
# control.yaml
vars : 
    delta : 1
ins : a
out : a
series :
  # First process
  - if : a < 10
    command : (a, delta) -> node programs/add.js -> a
    while : a < 8
  # Second process
  - if : a > 10
    command : (a, delta) -> node programs/substract.js -> a
```

In the example, we create a global variable named `delta`. The value is `1`. It can be changed later by the processes. But, for this example, we won't do any changes to `delta`'s value. Instead, we will change the value of `a`

We have two proceesses that run sequentially (you can also use `parallel` instead of `series`, it will be discussed in the next section).

The first process (`(a, delta) -> node programs/add.js -> a`) take `a` and `delta` as inputs. The output will then saved in global variable `a`, so that it can be used later. Chimera will execute this process only if `a < 10`. The process will then executed repeatedly while `a < 8`

Once the first process completed (or ignored in case of the initial condition unmet), the second process (`(a, delta) -> node programs/substract.js -> a`) will be executed. The second process will only be executed if `a > 10`.

The process above is logically equal to this flowchart: 

![chimera-control-flowchart](doc/chimera-control-flowchart.png)

__Note:__ Use this feature with care. Don't over do it. For a more complex logic-control, please put it on your program.

## Nested variable

The best and worst part of Javascript object is that you can add any key without any need to define structure. Chimera's global variable is actually a big javascript object.

Suppose you have variable `a`, you can then access `a.name`, `a.address` etc.

The following YAML file show you how a nested variable can be used.

```yaml
ins: a, b
out: c
verbose: true
series:
    - ('{"x":4,"z":5}') -> php programs/echo.php -> tmp
    - parallel:
        - series:
            - (a, b) -> php programs/add.php -> tmp.y.addResult
            - (tmp.y.addResult, tmp.x) -> php programs/multiply.php -> tmp.y.addResult
        - series:
            - (a, b) -> php programs/substract.php -> tmp.y.substractResult
            - (tmp.y.substractResult, tmp.x) -> php programs/multiply.php -> tmp.y.substractResult
    - (tmp.y.addResult, tmp.y.substractResult) -> php programs/multiply.php -> c
```

```sh
gofrendi@minastirith:~/chimera-framework$ chimera tests/chain-complex-vars.yaml 10 11
[INFO] PROCESS :      php programs/echo.php "{\"x\":4,\"z\":5}"<commit_msg>better documentation<commit_after># Advance Example

## Distributed Process

In the previous example, the sub-processes (Process 1, Process 2, and Process 3) was executed in a single computer.

Chimera-framework can also run in distributed scenario. Suppose Process 1 should be run in the server, and Process 2 should run in the client, we should divide the process into 4 steps.


![chimera-example-distributed](chimera-example-distributed.png)

Before we dive into the steps, we should prepare two more files.

```yaml
# server.yaml
(a , b) −> php tests/add.php −> c
```

`server.yaml` contains only a single process (`tests/add.php`). It takes `a` and `b` as inputs, and return `c` as output. Executing `chimera server.yaml 4 5` will return `9`.

```yaml
# process.yaml
ins: a, b, server
out: e
verbose : true
series :
    − parallel :
        # Process 1
        − (server, 'server.yaml', a, b)−> chimera−send −> c
        # Process 2
        − (a, b) −> php programs/add.php −> c
    # Process 3
    − (c, d) −> node programs/add.js −> e
```

This YAML chain file is basically similar to our previous example. The only difference is on Process 1 definition. This process takes 4 inputs. The first one is server address, the second one is server's YAML chain, and the last two inputs will be sent `server.yaml`'.

`chimera-send` is a utility to execute YAML chain file in other computer. Its first two parameters are `server address` and `server YAML chain file` respectively.

After preparing the files, we should proceed with these 4 steps:


* __Server side preparation__: In the server side, we need to provide:
    - `tests/add.php`
    - `server.yaml`

* __Server side execution__: After server preparation completed, we need to serve `server.yaml`, so that it is accessible from the network. In order to do this, we can execute `chimera-serve`, a utility to serve chains in the server:

```sh
chimera-serve
```

* __Client side preparation__: In the client side, we need to provide:
    - `tests/add.php`
    - `tests/add.js`
    - `process.yaml`

* __Client side execution__: After client preparation completed, we can then execute:

```sh
chimera process.yaml 4 5 http://server-address.com:3000
```

## Shorthand

Let's look at this example:

```yaml
# filename: add.yaml
ins: a, b
out: c
command: node add.js
```

You can invoke the chain by performing `chimera add.yaml 5 6`. Assuming you `add.js` works correctly, you should see `11` as result.
If you don't define `out` element, `_ans` will be used by default.

Chimera also provide some shorthand for your convenience. The above example can also be written as:


```yaml
# Now, we put ins and out into the command, separated by ->
# The format is: [input] -> [process] -> output
command: (a,b) -> node add.js -> c
```

if not specified, the out parameter is default to `_ans`

```yaml
ins: a, b
command: node add.js
```

You can also write the process as:
```yaml
command: (a, b) -> node add.js
```

or even:

```yaml
(a, b) -> node add.js
```

In some situation, your process might be so simple that you only need a single line javascript arrow function instead of a fully stand alone program. In that case, you can do this:

```yaml
(a, b) -> (x,y)=>{return parseFloat(x)+parseFloat(y)}
```

For more comprehensive information regarding anonymous javascript arrow function, please visit [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)

## Process control (branch and loop)

Sometime your process contains several simple logic (i.e: loop and branch). Please look at this example:

```yaml
# control.yaml
vars : 
    delta : 1
ins : a
out : a
series :
  # First process
  - if : a < 10
    command : (a, delta) -> node programs/add.js -> a
    while : a < 8
  # Second process
  - if : a > 10
    command : (a, delta) -> node programs/substract.js -> a
```

In the example, we create a global variable named `delta`. The value is `1`. It can be changed later by the processes. But, for this example, we won't do any changes to `delta`'s value. Instead, we will change the value of `a`

We have two proceesses that run sequentially (you can also use `parallel` instead of `series`, it will be discussed in the next section).

The first process (`(a, delta) -> node programs/add.js -> a`) take `a` and `delta` as inputs. The output will then saved in global variable `a`, so that it can be used later. Chimera will execute this process only if `a < 10`. The process will then executed repeatedly while `a < 8`

Once the first process completed (or ignored in case of the initial condition unmet), the second process (`(a, delta) -> node programs/substract.js -> a`) will be executed. The second process will only be executed if `a > 10`.

The process above is logically equal to this flowchart: 

![chimera-control-flowchart](chimera-control-flowchart.png)

__Note:__ Use this feature with care. Don't over do it. For a more complex logic-control, please put it on your program.

## Nested variable

The best and worst part of Javascript object is that you can add any key without any need to define structure. Chimera's global variable is actually a big javascript object.

Suppose you have variable `a`, you can then access `a.name`, `a.address` etc.

The following YAML file show you how a nested variable can be used.

```yaml
ins: a, b
out: c
verbose: true
series:
    - ('{"x":4,"z":5}') -> php programs/echo.php -> tmp
    - parallel:
        - series:
            - (a, b) -> php programs/add.php -> tmp.y.addResult
            - (tmp.y.addResult, tmp.x) -> php programs/multiply.php -> tmp.y.addResult
        - series:
            - (a, b) -> php programs/substract.php -> tmp.y.substractResult
            - (tmp.y.substractResult, tmp.x) -> php programs/multiply.php -> tmp.y.substractResult
    - (tmp.y.addResult, tmp.y.substractResult) -> php programs/multiply.php -> c
```

```sh
gofrendi@minastirith:~/chimera-framework$ chimera tests/chain-complex-vars.yaml 10 11
[INFO] PROCESS :      php programs/echo.php "{\"x\":4,\"z\":5}"
{'fraction_non_alphanumeric': 0.11121047069343956, 'fraction_numerical': 0.007316478335094708, 'mean_word_length': 3.512839325018342, 'pattern_counts': {'":': 8, '<': 11, '<?xml version=': 0, '>': 81, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5293780', 'n_tokens_mistral': 3861, 'n_tokens_neox': 3629, 'n_words': 1668}