A simple AI to simulate multiple methods call
Tags: ai, javascript, discuss, simulations
Published: 2019-08-28 08:37:58

# An introduction to the use case

## WHY
I've maded a simple js script to handle multiple method call with different params. The reasons why I needed this script are really simple:

1. Simulate multiple server-side methods with different params
2. Stress the server (or the client) with a lot of method calls
3. Test the strengthness of my server-side methods
4. Automate the server behaviours, because I don't want to trigger manually a lot of methods while develop.

## HOW
This script works in a simple way, it accepts an array of defined methods with an array of different params. So the script will call these methods with random params, simulating the execution of these methods.

## AI.js
The following is the implementation of the "AI":

```javascript
/**
 _______  ___             ___  _______ 
|   _   ||   |           |   ||       |
|  |_|  ||   |           |   ||  _____|
|       ||   |           |   || |_____ 
|       ||   |  ___   ___|   ||_____  |
|   _   ||   | |   | |       | _____| |
|__| |__||___| |___| |_______||_______|

@desc   a script to automate js method run
@author nicolacastellanidev@gmail.com
*/
function AI(...bindings) {
  if (!bindings) {
    throw new Error('AI cannot run without bindings');
  }
  this.bindings = bindings;
}

AI.prototype = {
  running: false,
  /** @desc run a random binding with random parameters*/
  run() {
    this.running = true;
    /** get a random method to call with random params */
    const randomBindingIndex = Math.floor(Math.random() * this.bindings[0].length);
    const binding = this.bindings[0][randomBindingIndex];
    const randomParamIndex = Math.floor(Math.random() * binding.withParams.length);
    
    /** call random binding */
    try {
      this.log(`>>> SIMULATING *** ${binding.method.name} *** WITH PARAMS *** ${Object.values(binding.withParams[randomParamIndex])} ***`);
      binding.method.call(this, ...Object.values(binding.withParams[randomParamIndex]));
    } catch (ex) {
      this.log(`>>> SIMULATING *** ${binding.method.name} *** WITH PARAMS *** ${binding.withParams[randomParamIndex]} ***`);
      this.log(`>>> ERROR: ${ex.message}`);
    }
    /** then set a random timeout for the next call */
    this.runTimeout = setTimeout(() => {
      this.run();
    }, (Math.floor(Math.random() * 5) + 2) * 1000);
  },
  /** @desc stop the AI execution */
  stop() {
    this.running = false;
    this.log(`>>> SIMULATION STOPPED`);
    clearTimeout(this.runTimeout);
  },

  /** @desc log method - appen a string to the console html element */
  log(what) {
    console.log(`${what}</br>`)
  }
};
```
### Fake methods implementation

```javascript
/**
* FAKE METHODS IMPLEMENTATION
*/
const fakeMethod = (url) => {
  console.log(`A fakeMethod has been called with url: ${url}`);
}

const sum = (a, b) => {
  console.log(`The sum is: ${a + b}`);
}

const diff = (a, b) => {
  console.log(`The diff is: ${a - b}`);
}
```

### AI initialization with fake methods

```javascript
/**
* AI INITIALIZATION
*/
const r2d2 = new AI(
  [
    {
      method: fakeMethod,
      withParams: [
        {url: '/simulate?action=1'},
        {url: '/simulate?action=2'},
      ]
    },
    {
      method: sum,
      withParams: [
        {a: 1, b: 1},
        {a: 1, b: 3}
      ]
    },
    {
      method: diff,
      withParams: [
        {a: 1, b: 1},
        {a: 3, b: 5}
      ]
    }
  ]
);
```

### Run the AI 
With the method __run__ you can start the simulations:
```javascript
r2d2.run();
```

### Stop the AI 
With the method __stop__ you can stop the simulations:
```javascript
r2d2.stop();
```

## Live example
{% codepen https://codepen.io/NicolaCastellaniDev/pen/RwbVgzb %}


# Conclusions
This is just an example, you can extend as you prefer with more complex simulations, or AI behaviours.